转换函数<对象,任务>to Func在运行时

本文关键字:Task 运行时 Func to 函数 任务 转换 对象 | 更新日期: 2023-09-27 18:07:51

我有一个Func<object, Task>。我试图把它作为一个参数传递给一个函数,它接受Func<T, Task>。我使用反射为该函数创建MethodInfo,并且填充的T直到运行时才知道。

如何使用反射来实现这一点?

转换函数<对象,任务>to Func<T, Task>在运行时

不需要做任何特别的事情

Func<in T, out TResult>T逆变 -它的输入参数,并且每个类型都继承自object,这意味着您可以将任何引用类型 T强制转换 Func<object, Task>Func<T, Task> -按原样传递它,它将正常工作。

例子

现在,这对值类型不起作用,因为这些值类型需要事先将拆箱。

所以,如果你的T是一个值类型,你必须包装它在另一个委托将执行强制类型转换。

一个简单的方法是定义一个包装器方法:
private static Func<T, TResult> CastFunc<T, TResult>(Func<object, TResult> fn)
    => param => fn(param);

然后通过反射创建一个委托:

var result = (Func<int, Task>)typeof(WrapperClass)
    .GetMethod(nameof(CastFunc), BindingFlags.NonPublic | BindingFlags.Static)
    .MakeGenericMethod(typeof(int), typeof(Task)).Invoke(null, new object[] { fn });

我会选择使用MakeGenericMethod

下面是一个简单的例子:

    public class Example
    {
        public void Start()
        {
             Func<object, Task> func = o => null;
             object objFunc = func; // got it from a generic place as an object or something
             Type type = objFunc.GetType().GetGenericArguments()[0]; // get T in runtime
             var method = typeof(Example).GetMethod("DoSomething", BindingFlags.Public | BindingFlags.Instance).MakeGenericMethod(type);
             var result = method.Invoke(this, new object[1] { func });
        }
        public int DoSomething<T>(Func<T, Task> input)
        {
            return 1;
        }
    }