我一直在玩,部分重新发明轮子,这样我才能理解轮子旋转的方式。
考虑这个泛型函数来编译和返回类型的默认构造函数。
public static Func<TConcrete> Creator<TConcrete>()
{
// All checking removed for brevity
var ctor = typeof(TConcrete).GetConstructor(new Type[0]);
var lambda = Expression.Lambda<Func<TConcrete>>(Expression.New(ctor));
return lambda.Compile();
}
我相信这会给我一个很好的类型委托,我可以使用它来实例化传递的类型。
现在考虑一下,我想要一个能够为一组不同类型执行此操作的函数,我将如何解决这个问题?我在沿着......的路线走来走去。
public static IEnumerable<Delegate> Creators(IEnumerable<Type> types)
{
foreach (var type in types)
{
var ctor = type.GetConstructor(new Type[0]);
var lamda = Expression.Lambda<Func<????>>(Expression.New(ctor));
yield return lambda.Compile();
}
}
从????
可以看出这就是我被卡住的地方。有没有办法做到这一点,还是我的做法只是有缺陷?
答案 0 :(得分:7)
您可以使用其他Expression.Lambda
调用,将委托类型设为Type
:
Type delegateType = typeof(Func<>).MakeGenericType(type);
var lambda = Expression.Lambda(delegateType, Expression.New(ctor));
yield return lambda.Compile();
请注意,此Lambda
的重载会返回非通用LambdaExpression
类型而不是Expression<TDelegate>
- 但它仍会显示返回Delegate
的{{3}}方法,这就是你需要的一切。基本上它只是避免了一些编译时类型检查,你可以从“已知的委托类型”代码中受益。
答案 1 :(得分:6)
将非泛型重载与MakeGenericType
结合使用:
var lamda = Expression.Lambda<Func<????>>(Expression.New(ctor));
应该成为:
var funcType = typeof(Func<>).MakeGenericType(type);
var lamda = Expression.Lambda(funcType, Expression.New(ctor));