[英]Creating an performant open delegate for an property setter or getter
[英]Using Open Delegate to access a struct property setter generate exception
为了序列化,我们尝试生成委托以动态更新一些对象属性值并将它们存储到列表中以供进一步使用。 只要我们不尝试反序列化结构,一切都很好。
我们的代码基于这篇关于开放代表的文章: http : //codeblog.jonskeet.uk/2008/08/09/making-reflection-fly-and-exploring-delegates/
这是我们的代码,用于处理基于类的对象中的属性设置器。
private static System.Action<object, object> ToOpenActionDelegate<T, TParam>(System.Reflection.MethodInfo methodInfo) where T : class
{
System.Type parameterType = typeof(TParam);
// Convert the slow MethodInfo into a fast, strongly typed, open delegate
System.Action<T, TParam> action = (System.Action<T, TParam>)System.Delegate.CreateDelegate(typeof(System.Action<T, TParam>), methodInfo);
// Convert the strong typed delegate into some object delegate!
System.Action<object, object> ret = (object target, object param) => action(target as T, (TParam)System.Convert.ChangeType(param, parameterType));
return ret;
}
正如您所猜测的那样,它不适用于struct。 我发现这篇文章讨论了如何在struct中处理open delegate: 如何从struct的实例方法创建一个open Delegate? (实际上,我找到了比这个更多的帖子,但是这个有一个“简单”的解决方案,例如不使用IL代码...)
但是,就目前而言,每当我尝试使用ref参数将属性setter的methodinfo绑定到委托时,我都会遇到异常。 这是我使用的当前代码:
public delegate void RefAction<T, TParam>(ref T arg, TParam param) where T : class;
private static RefAction<object, object> ToOpenActionDelegate<T, TParam>(System.Reflection.MethodInfo methodInfo) where T : class
{
// Convert the slow MethodInfo into a fast, strongly typed, open delegate
System.Type objectType = typeof(T);
System.Type parameterType = typeof(TParam);
RefAction<object, object> ret;
if (objectType.IsValueType)
{
RefAction<T, TParam> propertySetter = (RefAction<T, TParam>)System.Delegate.CreateDelegate(typeof(RefAction<T, TParam>), methodInfo);
// we are trying to set some struct internal value.
ret = (ref object target, object param) =>
{
T boxed = (T)target;
propertySetter(ref boxed, (TParam)System.Convert.ChangeType(param, parameterType));
target = boxed;
};
}
else
{
System.Action<T, TParam> action = (System.Action<T, TParam>)System.Delegate.CreateDelegate(typeof(System.Action<T, TParam>), methodInfo);
ret = (ref object target, object param) => action(target as T, (TParam)System.Convert.ChangeType(param, parameterType));
}
return ret;
}
执行以下行时出现问题:
RefAction<T, TParam> propertySetter = (RefAction<T, TParam>)System.Delegate.CreateDelegate(typeof(RefAction<T, TParam>), methodInfo);
至少对我而言,这与上面链接帖子中使用的相同:
SomeMethodHandler d = (SomeMethodHandler)Delegate.CreateDelegate(typeof(SomeMethodHandler), method);
哪里:
delegate int SomeMethodHandler(ref A instance);
public struct A
{
private int _Value;
public int Value
{
get { return _Value; }
set { _Value = value; }
}
private int SomeMethod()
{
return _Value;
}
}
任何人都知道为什么它会在我身边而不是在链接线程中产生异常? 它是否与C#运行时版本相关联? 我正在努力团结,所以这是一个几乎相当于3.5的单声道框架......
无论如何,感谢阅读,如果我在问题布局或语法中做错了,请不要犹豫!
干杯,弗洛。
您正在创建静态方法的委托而不是开放委托。 我在你的CreateDelegate
调用中添加了null
并且它有效(但我对性能不太确定,但是,使用双重装箱/取消装箱):
public struct S
{
public string Value {get; set;}
}
static class Program
{
public delegate void RefAction<T, TParam>(ref T arg, TParam param);
static RefAction<object, object> ToOpenActionDelegate<T, TParam>(System.Reflection.MethodInfo methodInfo)
{
// Convert the slow MethodInfo into a fast, strongly typed, open delegate
Type objectType = typeof(T);
Type parameterType = typeof(TParam);
RefAction<object, object> ret;
if (objectType.IsValueType)
{
RefAction<T, TParam> propertySetter = (RefAction<T, TParam>)Delegate.CreateDelegate(typeof(RefAction<T, TParam>), null, methodInfo);
// we are trying to set some struct internal value.
ret = (ref object target, object param) =>
{
T boxed = (T)target;
propertySetter(ref boxed, (TParam)System.Convert.ChangeType(param, parameterType));
target = boxed;
};
}
else
{
Action<T, TParam> action = (Action<T, TParam>)Delegate.CreateDelegate(typeof(Action<T, TParam>), null, methodInfo);
ret = (ref object target, object param) => action((T)target, (TParam)System.Convert.ChangeType(param, parameterType));
}
return ret;
}
public static void Main(string[] args)
{
var s = new S();
var mi = s.GetType().GetMethod("set_Value");
/*
var deleg = (RefAction<S, string>)Delegate.CreateDelegate(typeof(RefAction<S, string>), null, mi);
deleg(ref s, "hello");
RefAction<object, object> deleg2 = (ref object target, object param) => {
S boxed = (S)target;
deleg(ref boxed, (string)param);
target = boxed;
};
*/
RefAction<object, object> deleg2 = ToOpenActionDelegate<S, string>(mi);
var o = (object)s;
deleg2(ref o, "world");
s = (S)o;
Console.WriteLine(s.Value); //prints "world"
Console.ReadKey(true);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.