如何分配通过表达价值?(How to assign a value via Expression?)

2019-08-03 16:33发布

这将是,如果我能够通过Lambda表达式分配很简单(如下图)

//An expression tree cannot contain an assignment operator
Expression<Func<ComplexObj, object>> expression = obj => obj.Contacts[0].FirstName = "Tim";

上面这段代码是无效的,由于赋值运算符。 我需要传递,以便识别在复杂的对象需要被设置的属性的λ表达式。 在某些情况下,复杂的对象有列表和重复为此对象类型和名称这就是为什么我需要的拉姆达明确引用字段中的对象进行更新。

我能够检索使用以下,没有问题的值。 但我不知道如何使用这个相同的逻辑来设置的值,我碰到Expression.Assign并认为这可能是解决方案。

Expression<Func<ComplexObj, object>> expression = obj => obj.Contacts[0].FirstName;
var result = FindByProperty(expression);

public static string FindByProperty(Expression<Func<Contract, object>> propertyRefExpr)
{
    ComplexObj obj = new ComplexObj();
    Contact myContact = new Contact();
    myContact.FirstName = "Allen";
    obj.Contacts = new List<Contact>{myContact};
    return propertyRefExpr.Compile().Invoke(obj);
}

更新:

“传递一个属性赋值为表达式树的方法......”

使用具有ParentTypeA SetValue方法,价值将无法正常工作。 (下面的代码)

Expression<Func<ComplexObj, object>> expression = obj => obj.Contacts[0].FirstName;
obj.AssignNewValue(expression, firstName);

public static void AssignNewValue(this ComplexObj obj, Expression<Func<ComplexObj, object>> expression, object value)
{
    var propertyInfo = (PropertyInfo)((MemberExpression)expression.Body).Member;
    propertyInfo.SetValue(obj, value, null);
}

Answer 1:

最后我用以下解决方案。 干杯

ComplexObj obj = new ComplexObj();
Expression<Func<ComplexObj, object>> expression = obj => obj.Contacts[index].FirstName;
obj.AssignNewValue(expression, firstName);

public static void AssignNewValue(this ComplexObj obj, Expression<Func<ComplexObj, object>> expression, object value)
{
    ParameterExpression valueParameterExpression = Expression.Parameter(typeof(object));
    Expression targetExpression = expression.Body is UnaryExpression ? ((UnaryExpression)expression.Body).Operand : expression.Body;

    var newValue = Expression.Parameter(expression.Body.Type);
    var assign = Expression.Lambda<Action<ComplexObj, object>>
                (
                    Expression.Assign(targetExpression, Expression.Convert(valueParameterExpression, targetExpression.Type)),
                    expression.Parameters.Single(),
                    valueParameterExpression
                );

    assign.Compile().Invoke(obj, value);
}


Answer 2:

链接到的问题可能是“正确”的答案,但只是为了完整起见,你可以做更多的东西像这样...它不遵循“说,不问”的方法好一点,但我不能说我喜欢的实现...

void Main()
{
    Expression<Func<ComplexObj, object>> expression = 
      obj => obj.Contacts[0].SetFirstName("Tim");       
}

public class ComplexObj
{
    public ComplexObj() { Contacts = new List<SimpleObj>(); }
    public List<SimpleObj> Contacts {get; private set;}
}
public class SimpleObj
{
    public string FirstName {get; private set;}
    public SimpleObj SetFirstName(string name) { this.FirstName = name; return this; }
}


文章来源: How to assign a value via Expression?