问题描述
我正在尝试创建委托以在运行时读取/写入未知类型类的属性.
I am trying to create Delegate for reading/writing properties of unknown type of class at runtime.
我有一个通用类 Main<T>
和一个看起来像这样的方法:
I have a generic class Main<T>
and a method which looks like this:
Delegate.CreateDelegate(typeof(Func<T, object>), get)
其中 get
是应读取的属性的 MethodInfo
.问题是当属性返回 int
时(我猜这发生在值类型上)上面的代码抛出 ArgumentException 因为方法不能被绑定.如果是字符串,它工作得很好.
where get
is a MethodInfo
of the property that should be read. The problem is that when the property returns int
(I guess this happens for value types) the above code throws ArgumentException because the method cannot be bound. In case of string it works well.
为了解决这个问题,我更改了代码,以便使用 MakeGenericType
生成相应的委托类型.所以现在的代码是:
To solve the problem I changed the code so that corresponding Delegate type is generated by using MakeGenericType
. So now the code is:
Type func = typeof(Func<,>);
Type generic = func.MakeGenericType(typeof(T), get.ReturnType);
var result = Delegate.CreateDelegate(generic, get)
现在的问题是 generic
的创建委托实例,所以我必须使用 DynamicInvoke
这与使用纯反射读取字段一样慢.
The problem now is that the created delegate instance of generic
so I have to use DynamicInvoke
which would be as slow as using pure reflection to read the field.
所以我的问题是为什么第一段代码会因值类型而失败.根据 MSDN 它应该像它所说的那样工作
So my question is why is that the first snippet of code fails with value types. According to MSDN it should work as it says that
如果方法的返回类型比委托的返回类型更严格,则委托的返回类型与方法的返回类型兼容
The return type of a delegate is compatible with the return type of a method if the return type of the method is more restrictive than the return type of the delegate
以及如何在第二个片段中执行委托,使其比反射更快.
and how to execute the delegate in the second snippet so that it is faster than reflection.
谢谢.
推荐答案
这是解决问题的一种方法.创建一个泛型方法:
Here's one way to solve your problem. Create a generic method:
public static Func<T, object> MakeDelegate<U>(MethodInfo @get)
{
var f = (Func<T, U>)Delegate.CreateDelegate(typeof(Func<T, U>), @get);
return t => f(t);
}
这样,C# 的编译器负责插入必要的装箱(如果有)以将 f(t)
(类型为 U
)转换为 object代码>.现在你可以使用反射来调用这个
MakeDelegate
方法,并将 U
设置为 @get.ReturnType
,你得到的将是一个 >Func
无需使用 DynamicInvoke
即可调用.
This way, C#'s compiler takes care of inserting the necessary boxing (if any) to convert f(t)
(of type U
) to object
. Now you can use reflection to call this MakeDelegate
method with U
set to @get.ReturnType
, and what you get back will be a Func<T, object>
which can be called without needing to resort to using DynamicInvoke
.
这篇关于具有未知类型的 CreateDelegate的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!