Is it possible to encode an assignment into an expression tree?
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
You could probably work around it by nexting expression trees. Call a lambda function, where an argument is the value of the assignee.
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();
}
}
}
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()
.