将表达式树中生成的值传递给子树

时间:2013-08-12 10:34:23

标签: c# expression-trees

如果我在外表达式树中声明:

var creatorExpression = Expression.New(targetType);

我想在一个或多个子表达式中使用它,它们为新实例的属性赋值,例如:

var assignmentExpression = Expression.Assign(targetMemberExpression, valueExpression);

我该如何解决这个问题?

目前我将所有赋值表达式放入Expression.Block,但我看不到将实例传递到此块的方法。它需要ParameterExpressions,但我没有传递实例;我正在传递需要构建的类型。

1 个答案:

答案 0 :(得分:2)

类似的东西:

Type targetType = typeof(MyClass);

var obj = Expression.Variable(targetType);

var creatorExpression = Expression.New(targetType);
var assign = Expression.Assign(obj, creatorExpression);

var prop = Expression.PropertyOrField(obj, "MyProp1");
var value = Expression.Constant(5);
var member = Expression.Assign(prop, value);

var block = Expression.Block(new[] { obj }, creatorExpression, assign, member);

你必须记住Expression.New(targetType)new something(),所以如果你在其他地方直接使用它,你每次都在重新创建对象。你不想要:

new MyClass().MyProp1 = 5;
new MyClass().MyProp2 = 6;

你想要

var obj = new MyClass(); // assign + creatorExpression 
obj.MyProp1 = 5; // member + prop + value
obj.MyProp2 = 6; // not in the example

如果您知道要访问的媒体资源/字段是属性或字段,则可以使用Expression.PropertyExpression.Field。两者都接受string作为属性/字段名称或PropertyInfo / MethodInfo可以通过反思获得。

如果您有一个执行赋值的函数并返回带有赋值的块,则可以将obj表达式传递给它,如:

BlockExpression MakeSomeAssignments(ParameterExpression obj, Expression value1, int value2)
{
    var prop1e = Expression.PropertyOrField(obj, "MyProp1");
    var member1e = Expression.Assign(prop1e, value1e);

    var prop2e = Expression.PropertyOrField(obj, "MyProp2");
    var value2e = Expression.Constant(value2);
    var member2e = Expression.Assign(prop2e, value2e);

    return new Expression.Block(member1e, member2e);
}