简体   繁体   English

转换功能 <object, Task> 到功能 <T, Task> 在运行时

[英]Convert Func<object, Task> to Func<T, Task> at runtime

I have a Func<object, Task> . 我有一个Func<object, Task> I am trying to pass it as an argument into a function that takes Func<T, Task> . 我试图将其作为参数传递给采用Func<T, Task>的函数。 I am using reflection to create a MethodInfo for the function, and the T being filled in is not known until runtime. 我正在使用反射为该函数创建MethodInfo ,并且直到运行时才知道要填充的T

How can I do this with reflection? 我该如何进行反思?

You don't need to do anything special. 不需要做什么特别的。

Func<in T, out TResult> is contravariant on T - its input parameter, and every type inherits from object , which means you can just cast Func<object, Task> to Func<T, Task> for any reference type T - pass it as-is and it will just work. Func<in T, out TResult>T输入参数相反 ,每种类型都继承自object ,这意味着您可以 Func<object, Task> Func<T, Task>Func<T, Task>任何引用类型 T -pass照原样,它将正常工作。

Example

Now, this won't work for value types, since those require unboxing beforehand. 现在,这不适用于值类型,因为这些值类型需要事先拆箱

So if your T is a value type, you'll have to wrap it in another delegate which will perform a cast. 因此,如果您的T是值类型,则必须将其包装在另一个执行强制转换的委托中。

One simple way would be to define a wrapper method: 一种简单的方法是定义包装方法:

private static Func<T, TResult> CastFunc<T, TResult>(Func<object, TResult> fn)
    => param => fn(param);

Then create a delegate through reflection: 然后通过反射创建一个委托:

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

I'd go for reflection using MakeGenericMethod 我会使用MakeGenericMethod进行反思

Here's a quick example: 这是一个简单的示例:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM