使用对象初始值设定项创建实例的表达式

age*_*t47 17 c# lambda expression dynamic expression-trees

有没有办法用对象初始化器和表达式树创建对象的实例?我的意思是创建一个表达式树来构建这个lambda:

// my class
public class MyObject {
    public bool DisplayValue { get; set; }
}

// my lambda:
var lambda = (Func<bool, MyObject>)
             (displayValue => new MyObject { DisplayValue = displayValue });
Run Code Online (Sandbox Code Playgroud)

如何使用表达式树创建此lambda?

更新:

我试着自己编写以下代码:

    public static Func<bool, dynamic> Creator;

    static void BuildLambda() {
        var expectedType = typeof(MyObject);
        var displayValueParam = Expression.Parameter(typeof(bool), "displayValue");
        var ctor = Expression.New(expectedType);
        var local = Expression.Parameter(expectedType, "obj");
        var displayValueProperty = Expression.Property(ctor, "DisplayValue");

        var returnTarget = Expression.Label(expectedType);
        var returnExpression = Expression.Return(returnTarget,local, expectedType);
        var returnLabel = Expression.Label(returnTarget, Expression.Default(expectedType));

        var block = Expression.Block(
            new[] { local },
            Expression.Assign(local, ctor),
            Expression.Assign(displayValueProperty, displayValueParam),
            Expression.Return(Expression.Label(expectedType), local, expectedType),
            returnExpression,
            returnLabel
            );
        Creator =
            Expression.Lambda<Func<bool, dynamic>>(block, displayValueParam)
                .Compile();
    }
Run Code Online (Sandbox Code Playgroud)

但它会引发以下错误:

无法跳转到未定义的标签''.

大家能帮帮我吗?

svi*_*ick 48

要在Expression中表示对象初始值设定项,您应该使用Expression.MemberInit():

Expression<Func<bool, MyObject>> BuildLambda() { 
    var createdType = typeof(MyObject);
    var displayValueParam = Expression.Parameter(typeof(bool), "displayValue"); 
    var ctor = Expression.New(createdType);
    var displayValueProperty = createdType.GetProperty("DisplayValue");
    var displayValueAssignment = Expression.Bind(
        displayValueProperty, displayValueParam);
    var memberInit = Expression.MemberInit(ctor, displayValueAssignment);

    return
        Expression.Lambda<Func<bool, MyObject>>(memberInit, displayValueParam);
}
Run Code Online (Sandbox Code Playgroud)

要验证这实际上是否符合您的要求,您可以调用ToString()创建的表达式.在这种情况下,输出符合预期:

displayValue => new MyObject() {DisplayValue = displayValue}
Run Code Online (Sandbox Code Playgroud)