具有未知类型的 CreateDelegate

CreateDelegate with unknown types(具有未知类型的 CreateDelegate)
本文介绍了具有未知类型的 CreateDelegate的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建委托以在运行时读取/写入未知类型类的属性.

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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)