Search code examples
c#linqlambdaexpression-trees

Expression to Set Properties on Existing Object Instance


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.


Solution

  • 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.