Search code examples
c#.net-4.0.net-3.5expressionexpression-trees

Implementation of Expression.Assign in .Net 3.5 with same signature?


Expression.Assign isn't available before .NET 4. I need to implementation under .NET 3.5 of this method with original signature:

public static BinaryExpression Assign(
    Expression left,
    Expression right
)

Clarification: I'm not looking for a way to use this method in the some case. I need to implement the general case.


Solution

  • You can't get exact equivalent since there is no ExpressionType.Assign, but it's possible to make something similar:

    
    public static class ExpressionEx
    {
        public static BinaryExpression Assign(Expression left, Expression right)
        {
            var assign = typeof(Assigner<>).MakeGenericType(left.Type).GetMethod("Assign");
    
            var assignExpr = Expression.Add(left, right, assign);
    
            return assignExpr;
        }
    
        private static class Assigner<T>
        {
            public static T Assign(ref T left, T right)
            {
                return (left = right);
            }
        }
    }
    
    

    Then you can use it for generating assignments:

    
    class Foo
    {
        public int Data
        {
            get;
            set;
        }
    }
    
    class Program
    {
        static Action<object, object> MakeSetter(PropertyInfo info)
        {
            var objectParameter = Expression.Parameter(typeof(object), string.Empty);
            var valueParameter = Expression.Parameter(typeof(object), string.Empty);
            var setterExpression = Expression.Lambda<Action<object, object>>(
                ExpressionEx.Assign(
                    Expression.Property(
                        Expression.Convert(objectParameter, info.DeclaringType),
                        info),
                    Expression.Convert(valueParameter, info.PropertyType)),
                objectParameter,
                valueParameter);
    
            return setterExpression.Compile();
        }
    
        static void Main()
        {
            var foo = new Foo();
            var property = typeof(Foo).GetProperty("Data");
    
            var setter = MakeSetter(property);
            setter(foo, 10);
            Console.WriteLine(foo.Data);
        }
    }
    
    

    If you don't really need BinaryExpression as a return type you could use Expression.Call instead of Add so it would be not so hackish.