使用类型的类型创建编译的构造函数表达式

Jod*_*ell 5 c# reflection lambda delegates

我一直在玩,部分重新发明轮子,这样我就能理解轮子是如何旋转的.

考虑这个泛型函数来编译和返回类型的默认构造函数.

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();
}
Run Code Online (Sandbox Code Playgroud)

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

现在考虑一下,我想要一个能够为一组不同类型执行此操作的函数,我将如何进行此操作?我在沿着...的路线走来走去

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

从你可以看到????这是我被卡住的地方.有没有办法做到这一点,还是我的做法只是有缺陷?

Jon*_*eet 7

您可以使用不同的Expression.Lambda调用,将委托类型作为Type:

Type delegateType = typeof(Func<>).MakeGenericType(type);
var lambda = Expression.Lambda(delegateType, Expression.New(ctor));
yield return lambda.Compile();
Run Code Online (Sandbox Code Playgroud)

请注意,这个重载Lambda返回非泛型LambdaExpression类型而不是Expression<TDelegate>- 但它仍然暴露了一个Compile返回的方法Delegate,这就是你需要的.基本上它只是避免了一些编译时类型检查,你可以从"已知的委托类型"代码中受益.


Kir*_*oll 6

将非泛型重载与MakeGenericType以下内容结合使用:

var lamda = Expression.Lambda<Func<????>>(Expression.New(ctor));
Run Code Online (Sandbox Code Playgroud)

应该成为:

var funcType = typeof(Func<>).MakeGenericType(type);
var lamda = Expression.Lambda(funcType, Expression.New(ctor));
Run Code Online (Sandbox Code Playgroud)