2012-06-21 20 views
4

制作一个编译好的构造函数表达式我一直在玩耍,部分地重新发明轮子,以便我能够理解轮子是如何旋转的。仅使用类型

考虑用于编译和返回类型的默认构造函数的这个通用函数。

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

我相信这会返回一个很好的类型委托,我可以用来实例化传递的类型。

现在考虑一下,我想要一个函数来处理一组不同类型的数据,我该怎么做呢?我沿着线thiking ...

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

代码如何调用'Creators'方法并使用返回的委托? – dtb

+0

@dtb,该代码实际上并不存在,我的程序实际上有一个函数,它使用'IEnumerable >'在接口和具体实现之间传递关联,但是,我认为这对我的实际问题是多余的。 – Jodrell

回答

5

使用组合的非通用超载与MakeGenericType

var lamda = Expression.Lambda<Func<????>>(Expression.New(ctor)); 

应该改为:

var funcType = typeof(Func<>).MakeGenericType(type); 
var lamda = Expression.Lambda(funcType, Expression.New(ctor)); 
+0

该死的,很明显,谢谢 – Jodrell

6

您可以使用不同的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> - 但它仍然公开Compile方法,该方法返回Delegate,这是您在此处需要的全部内容。基本上它只是避免一些编译时类型检查你在“已知委托类型”代码中受益。

+0

的确,谢谢。我应该花一些时间阅读我的intellisense。 – Jodrell