views:

1471

answers:

4

Is it possible to encode an assignment into an expression tree?

+6  A: 

No, I don't believe so.

Certainly the C# compiler disallows it when converting a lambda expression:

int x;
Expression<Func<int,int>> foo = (x=y); // Assign to x and return value

This yields the error:

CS0832: An expression tree may not contain an assignment operator
Jon Skeet
+1  A: 

You could probably work around it by nexting expression trees. Call a lambda function, where an argument is the value of the assignee.

TraumaPony
+6  A: 

You should able to do it with .NET 4.0 Library. by import Microsoft.Scripting.Core.dll to your .NET 3.5 project.

I am using DLR 0.9 - There might be some change on Expession.Block and Expression.Scope in version 1.0 (You can see reference from http://www.codeplex.com/dlr/Thread/View.aspx?ThreadId=43234)

Following sample is to show you.

using System;
using System.Collections.Generic;
using Microsoft.Scripting.Ast;
using Microsoft.Linq.Expressions;
using System.Reflection;

namespace dlr_sample
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Expression> statements = new List<Expression>();

            ParameterExpression x = Expression.Variable(typeof(int), "r");
            ParameterExpression y = Expression.Variable(typeof(int), "y");

            statements.Add(
                Expression.Assign(
                    x,
                    Expression.Constant(1)
                )
             );

            statements.Add(
                Expression.Assign(
                    y,
                    x
                )
             );

            MethodInfo cw = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(int) });

            statements.Add(
                Expression.Call(
                    cw,
                    y
                )
            );

            LambdaExpression lambda = Expression.Lambda(Expression.Scope(Expression.Block(statements), x, y));

            lambda.Compile().DynamicInvoke();
            Console.ReadLine();
        }
    }
}
Jirapong
+1  A: 

As Jon Skeet and TraumaPony have already said, Expression.Assign isn't available before .NET 4. Here's another concrete example of how to work around this missing bit:

public static class AssignmentExpression
{
    public static Expression Create(Expression left, Expression right)
    {
        return
            Expression.Call(
               null,
               typeof(AssignmentExpression)
                  .GetMethod("AssignTo", BindingFlags.NonPublic | BindingFlags.Static)
                  .MakeGenericMethod(left.Type),
               left,
               right);
    }

    private static void AssignTo<T>(ref T left, T right)  // note the 'ref', which is
    {                                                     // important when assigning
        left = right;                                     // to value types!
    }
}

Then simply call AssignmentExpression.Create() in place of Expression.Assign().

stakx