无法使用 V 将 Func<T1, T2<U>> 转换为 Func<T1, T2<V>> : U

cannot cast Func<T1, T2<U>> to Func<T1, T2<V>> with V : U

我有一个返回 Func<ConstructorInfo, MyDelegate<T>> 的方法,其中 MyDelegate 是一个通用(协变)委托。现在我想将此方法的结果分配给 Func<ConstructorInfo, MyDelegate<U>> 类型的变量,其中 UT (T : U) 的基数 class。但是我得到 InvalidCastException。这是因为 Func 不是协变的(至少在 .NET 3.5 中是这样)还是我该如何解决这个问题?

编辑一些代码:

using System;
using System.Reflection;
using System.Linq.Expressions;

public delegate T MyDelegate<out T>(params object[] args);

class GenericTypeFactory
{
    public static MyDelegate<T> GetActivator<T>(ConstructorInfo ctor) 
    { 
            // make a NewExpression that calls the ctor with the args we
            // just created
            var newExp = Expression.New(ctor);
            var lambda = Expression.Lambda(typeof(MyDelegate<T>), newExp);
            var compiledExpression = (MyDelegate<T>)lambda.Compile();
            return compiledExpression;
    }
}

而在我的主-class:

using System;
using System.Reflection;
using System.Linq.Expressions;

class MyClass {
    private Func<ConstructorInfo, MyDelegate<T>> createLambdaExpression<T>()
    {
        // this Func is only introduced to ensure name-safety when
        // refactoring the GenericTypeFactor.GetActivator-method 
        // (changing params, other name, ...) we could also use
        // Reflection to get this method by its name the generic-type
        // argument <T> is only a placeholder
        Func<ConstructorInfo, Delegate> myFunc = 
            GenericTypeFactory.GetActivator<T>;

        MethodInfo method = myFunc.Method;
        // set the params for the method we obtained above
        var paramExp = Expression.Parameter(typeof(ConstructorInfo), "ctor");
        // call the method with its params
        var call = Expression.Call(method, paramExp);                
        return Expression.Lambda<Func<ConstructorInfo, MyDelegate<T>>>(
                call, 
                paramExp)
            .Compile();
    }

    void DoSomeThing<T>()
    {
        Type customType = typeof(T); // not really, but for simplicity
        // type T is only a dummy-type (replaced in next line)
        Func<Delegate> myFunc = this.createLambdaExpression<T>; 
        MethodInfo method = 
            myFunc.Method.GetGenericMethodDefinition()
            .MakeGenericMethod(customType);
        var getActivator = (Func<ConstructorInfo, MyDelegate<T>>)
            method.Invoke(this, null);
    }
}

我仍然不确定为什么它没有像我上面发布的那样工作。现在我找到了另一种方法,至少有效(虽然它不是我最喜欢的)。为此,我只是将我的 createLambdaExpression 方法的结果投射到委托而不是具体的 Func,并调用它的 DynamicInvoke 方法。考虑到性能,这当然不是最佳选择,但是当我缓存所有激活器时,我只需要调用一次而不是总是调用它,我需要一个特定类型的新实例。

Func<Delegate> myFunc = this.createLambdaExpression<T>;
MethodInfo method = myFunc.Method.GetGenericMethodDefinition().MakeGenericMethod(customType);
var getActivator = (Delegate)method.Invoke(this, null);
var activator = (Delegate)getActivator.DynamicInvoke(new[] { ctor });

最后我调用了 ((ObjectActivator<T>) activator)(),这将 return 一个 customType 类型的新实例。