使用对象初始值设定项创建实例的表达式
有没有办法用对象初始化器和表达式树创建对象的实例? 我的意思是创建一个表达式树来构建这个lambda:
// my class public class MyObject { public bool DisplayValue { get; set; } } // my lambda: var lambda = (Func) (displayValue => new MyObject { DisplayValue = displayValue });
如何使用表达式树创建此lambda?
更新:
我试着自己编写以下代码:
public static Func 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>(block, displayValueParam) .Compile(); }
但它会引发以下错误:
无法跳转到未定义的标签”。
大家能帮帮我吗?
要在Expression中表示对象初始值设定项,您应该使用Expression.MemberInit()
:
Expression> 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>(memberInit, displayValueParam); }
要validation这实际上是否符合您的要求,您可以在创建的表达式上调用ToString()
。 在这种情况下,输出符合预期:
displayValue => new MyObject() {DisplayValue = displayValue}
最后我找到了答案:
public static Func 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(local, "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), /* I forgot to remove this line: * Expression.Return(Expression.Label(expectedType), local, expectedType), * and now it works. * */ returnExpression, returnLabel ); Creator = Expression.Lambda>(block, displayValueParam) .Compile(); }
更新:
虽然它工作正常,但@svick在他的回答中提供了一个更好更短的方式,我正在寻找: MemberInit
。 请参阅@ svick的回答。