How to assign a value through an expression?

It would be very simple if I could assign through 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 not valid due to the assignment operator. I need to pass a lambda expression to define a property in a complex object that needs to be set. In some cases, a complex object has a List and therefore duplicates the types and names of objects, so I need a lambda to explicitly refer to a field in the updated object.

I can get the value using the following, no problem. But I'm not sure how to use the same logic to set the value, I came across Expression.Assign and I think that 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 property assignment to a method as an expression tree ..."

Using the SetValue method with ParentTypeA, the 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); } 
+7
source share
2 answers

I ended up using the following solution. Greetings

 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); } 
+12
source

The related question is probably the โ€œrightโ€ answer, but just for the sake of completeness, you could do something more like this ... it improves the โ€œtell me not askโ€ methodology a bit, although I can't say what I like implementation ...

 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; } } 
0
source

All Articles