У меня есть метод, возвращающий Func<ConstructorInfo, MyDelegate<T>>
, где MyDelegate
является общим (ковариантным) делегатом. Теперь я хочу присвоить результат этого метода переменной типа Func<ConstructorInfo, MyDelegate<U>>
, где U
является базовым классом от T
(T: U). Но я получаю InvalidCastException
. Это потому, что Func
не является ковариантным (по крайней мере, в .NET 3.5) или как я могу это исправить?не может отличить Func <T1, T2<U>> to Func <T1, T2<V>> с V: U
EDIT некоторого код:
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;
}
}
И в моем основном классе:
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);
}
}
Вы используете * .NET 3.5? Это действительно поможет, если вы дадите более подробную информацию о своей среде и короткую, но полную программу, демонстрирующую проблему. –
Yeap, я использую 3.5. Подождите немного, мне нужно построить короткую тестовую программу ... – HimBromBeere
@JonSkeet Это не имеет ничего общего с версией .NET Framework. –