从反射创建通用的 Func

5

我已经在变量中指定了类型:Type hiddenType。我需要创建一个 Func<T> 委托,其中 T 是在上述变量中指定的类型,并将一个方法分配给它:

var funcType = typeof(Func<>).MakeGenericType(hiddenType);
Func<object> funcImplementation = () => GetInstance(hiddenType);

var myFunc= Delegate.CreateDelegate(funcType , valueGenerator.Method);

它不起作用-因为funcImplementation返回object而不是所需的类型。在运行时,它肯定是hiddenType指定类型的实例。

GetInstance返回object,签名不能更改。


1
我不明白你想要实现什么。由于GetInstance的声明返回值只是object,所以在这里使用Func<object>是完全正确的。 - MakePeaceGreatAgain
2
@HimBromBeere OPтИїТюЏmyFuncТў»Func<HiddenType>УђїСИЇТў»Func<object>сђѓС╗ќт░ЮУ»ЋСй┐ућеCreateDelegate№╝їСйєТ▓АТюЅТѕљтіЪсђѓ - Sergey Kalinichenko
2个回答

3
你可以通过手动构建表达式树,并插入一个到hiddenType的强制类型转换来解决这个问题。在构建表达式树时允许执行此操作。
var typeConst = Expression.Constant(hiddenType);
MethodInfo getInst = ... // <<== Use reflection here to get GetInstance info
var callGetInst = Expression.Call(getInst, typeConst);
var cast = Expression.Convert(callGetInst, hiddenType);
var del = Expression.Lambda(cast).Compile();

注意:上面的代码假设 GetInstance 是静态的。如果它不是静态的,那么修改构造 callGetInst 的方式,将方法所在的对象传递进去。


然而,生成的委托并不是强类型的,我认为原帖作者实际上想要的是强类型的委托。 - MakePeaceGreatAgain
@HimBromBeere 这个委托将是强类型的,其类型将与 typeof(Func<>).MakeGenericType(hiddenType) 兼容。当然,它不会是静态类型的委托(因为类型是隐藏的,所以这是不可能的)。 - Sergey Kalinichenko
谢谢!我曾经想过 Expression 可以做到这件事,但我不知道如何吃掉那块蛋糕。 - user2160375

0

如果无法更改GetInstance签名,请考虑使用通用包装器代替使用Type:

private Func<THidden> GetTypedInstance<THidden>()
{
    return () => (THidden)GetInstance(typeof(THidden));
}

然后你可以直接调用它

GetTypedInstance<SomeClass>();

而不是

GetInstance(typeof(SomeClass));

3
我认为问题在于 hiddenType 只有在运行时才能确定,因此静态绑定到通用包装器将无法使用。 - MakePeaceGreatAgain

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接