5

我一直在玩,部分地重新发明轮子,这样我就可以理解正确的轮子是如何旋转的。

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

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

正如你所看到的,????这就是我被卡住的地方。有没有办法做到这一点,还是我的方法有缺陷?

4

2 回答 2

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>- 但它仍然公开了一个Compile返回的方法Delegate,这就是您在这里所需要的。基本上,它只是避免了您从“已知委托类型”代码中受益的一些编译时类型检查。

于 2012-06-21T16:59:03.907 回答
6

结合使用非泛型重载MakeGenericType

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

应该变成:

var funcType = typeof(Func<>).MakeGenericType(type);
var lamda = Expression.Lambda(funcType, Expression.New(ctor));
于 2012-06-21T16:57:34.870 回答