【问题标题】:Making a compiled constructor expression with just the Type of the type仅使用类型的类型制作编译的构造函数表达式
【发布时间】:2012-06-21 16:55:29
【问题描述】:

我一直在玩,部分地重新发明轮子,以便了解正确的轮子是如何旋转的。

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

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

正如您从???? 中看到的那样,这就是我被卡住的地方。有没有办法做到这一点,还是我的方法有缺陷?

【问题讨论】:

  • 调用Creators 方法并使用返回的委托的代码看起来如何?
  • @dtb,该代码实际上并不存在,我的程序实际上有一个函数,它需要一个 IEnumerable&lt;KeyValuePair&lt;Type, Type&gt;&gt; 来传递接口和具体实现之间的关联,但是,我认为这对我的实际问题是多余的.

标签: c# reflection delegates lambda


【解决方案1】:

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

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

请注意,Lambda 的重载返回非泛型 LambdaExpression 类型而不是 Expression&lt;TDelegate&gt; - 但它仍然公开了一个返回 DelegateCompile 方法,这就是您在这里所需要的。基本上,它只是避免了一些编译时类型检查,您可以从“已知委托类型”代码中受益。

【讨论】:

  • 确实,谢谢。我应该花一些时间在那里阅读我的智能感知。
【解决方案2】:

将非泛型重载与MakeGenericType 结合使用:

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

应该变成:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多