1

How can I use Expression to set properties on an instance of an object I already have? I don't want to create a new object, so Expression.New where you can pass in member initializers won't work.

This is not a duplicate of How to set property value using Expressions? because that takes an Expression and sets properties via Reflection.

I have an existing object and want to create an Expression where I can set properties. That expression will then get compiled into a delegate to execute.

Josh Close
  • 22,935
  • 13
  • 92
  • 140
  • Possible duplicate of [How to set property value using Expressions?](https://stackoverflow.com/questions/9601707/how-to-set-property-value-using-expressions) – George Alexandria Sep 22 '17 at 22:43
  • 2
    Expression.Assign into Expression.Property of your object (either as a ConstantExpression or ParameterExpression depending on how you're using it) passing the PropertyInfo of the property you want to assign – pinkfloydx33 Sep 22 '17 at 23:04

2 Answers2

2

what about:

public class User {
    public string Name {get;set;}
}

public static void Main()
{
    var user = new User();
    var assigner = GetAssigner<User, string>(u => u.Name);
    assigner.Compile()(user, "Joe");
    Console.WriteLine(user.Name);
}

public static Expression<Action<TClass, TValue>> GetAssigner<TClass, TValue>(Expression<Func<TClass, TValue>> propertyAccessor){
    var prop = ((MemberExpression)propertyAccessor.Body).Member;
    var typeParam = Expression.Parameter(typeof(TClass));
    var valueParam = Expression.Parameter(typeof(TValue));
    return Expression.Lambda<Action<TClass, TValue>>(
        Expression.Assign(
            Expression.MakeMemberAccess(typeParam, prop),
            valueParam), typeParam, valueParam);

}

Remember that the expression is just a definition of what should be done, you have to compile it to a delegate to be able to invoke it.

MBoros
  • 1,090
  • 7
  • 19
  • The combination of `Expression.Assign` with `Expression.MakeMemberAccess` is exactly what I was looking for. – Josh Close Sep 24 '17 at 14:53
1

Have you looked at using MemberAssignment to set the value of the member(s)?

Represents assignment operation for a field or property of an object.

Important note in the remarks, however: you can't create these directly. Instead,

Use the Bind factory methods to create a MemberAssignment. A MemberAssignment has the BindingType property equal to Assignment.

Josh E
  • 7,390
  • 2
  • 32
  • 44
  • I have a list of `MemberAssignment`s. How do I create an `Expression` to assign those to an existing object? I can do it when creating a new object via `Expression.New`, but I don't know how to do it with an existing object. – Josh Close Sep 22 '17 at 22:59
  • It’s been a while, but I seem to recall `MemberAssignment` being specifically for object initializer expressions, like `new X { Member = y }`. A plain old `Assign(Property(x, "Member"), y),` should be fine. – Mike Strobel Sep 23 '17 at 16:18
  • The docs don't mention object initializer expressions, perhaps you're thinking of [MemberInitExpression](https://msdn.microsoft.com/en-us/library/system.linq.expressions.memberinitexpression(v=vs.110).aspx)? – Josh E Sep 24 '17 at 01:07
  • @JoshClose pass the property to get/set as a ParameterExpression after all, property setter are really just method calls accepting a parameter corresponding to the value to update – Josh E Sep 24 '17 at 01:08