gpt4 book ai didi

c# - 使用 Open Delegate 访问结构属性 setter 生成异常

转载 作者:太空狗 更新时间:2023-10-29 21:56:57 29 4
gpt4 key购买 nike

出于序列化的目的,我们试图生成委托(delegate)来动态更新一些对象属性值并将它们存储到列表中以供进一步使用。只要我们不尝试反序列化结构,一切都运行良好。

我们的代码基于这篇关于开放委托(delegate)的文章:http://codeblog.jonskeet.uk/2008/08/09/making-reflection-fly-and-exploring-delegates/

这是我们在基于类的对象中处理属性 setter 的代码。

    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。我发现这篇文章谈论如何处理结构中的开放委托(delegate): How can I create an open Delegate from a struct's instance method?(实际上,我发现的帖子比这个多得多,但是这个有一个“简单”的解决方案,例如不使用 IL 代码生成...)

但是,目前,每次我尝试使用 ref 参数将属性 setter 的方法信息绑定(bind)到委托(delegate)时,都会出现异常。这是我当前使用的代码:

    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# 运行时版本?我正在研究 unity,所以它是一个几乎等同于 3.5 的单声道框架...

无论如何,感谢阅读,如果我在问题布局或语法上做错了什么,请不要犹豫!

干杯,弗洛。

最佳答案

您正在为静态方法而不是开放委托(delegate)创建委托(delegate)。我将 null 添加到您的 CreateDelegate 调用中并且它有效(不过,我不太确定性能,使用双装箱/拆箱):

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);
}
}

关于c# - 使用 Open Delegate 访问结构属性 setter 生成异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34743176/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com