Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to assign a value via Expression?

This would be very simple if I were able to assign via a Lambda expression (below)

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

This code above is invalid due to the assignment operator. I need to pass a lambda expression in order to identify the property in the complex object that needs to be set. In some cases the complex object has List and therefor duplicate object types and names which is why I need the lambda to explicitly reference the field in the object to be updated.

I am able to retrieve the value using the following, no problem. But I am not sure how to use this same logic to set the value, I came across Expression.Assign and believe this may be the solution.

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

Update:

"passing a property assignment to a method as an expression tree..."

Using the SetValue method with ParentTypeA, Value will not work. (below code)

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);
}
like image 639
AnxiousdeV Avatar asked Dec 07 '12 19:12

AnxiousdeV


People also ask

How do you assign an expression?

Assignment expression are written with a new notation (:=) . This operator is often called the walrus operator as it resembles the eyes and tusks of a walrus on its side. The assignment expression allows you to assign True to walrus , and immediately print the value.

How do you assign an expression to a variable?

JavaScript uses the = operator to assign a value to a variable or property. For example: i = 0 // Set the variable i to 0. o .

How do you execute an expression?

Only expression trees that represent lambda expressions can be executed. Expression trees that represent lambda expressions are of type LambdaExpression or Expression<TDelegate>. To execute these expression trees, call the Compile method to create an executable delegate, and then invoke the delegate.


1 Answers

I ended up using the following solution. Cheers

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);
}
like image 144
AnxiousdeV Avatar answered Oct 06 '22 00:10

AnxiousdeV