Binary expression for lambda

This may be familiar to some. I have an Ex wrapper class that wraps an expression tree with a bunch of implicit conversions and operators. Here is a simplified version

 public class Ex { Expression expr; public Ex(Expression expr) { this.expr = expr; } public static implicit operator Expression(Ex rhs) { return rhs.expr; } public static implicit operator Ex(double value) { return new Ex(Expression.Constant(value, typeof(double))); } public static implicit operator Ex(string x) { return new Ex(Expression.Parameter(typeof(double), x)); } public static Ex operator +(Ex left, Ex right) { return new Ex(Expression.Add(left, right)); } public static Ex operator -(Ex rhs) { return new Ex(Expression.Negate(rhs)); } public static Ex operator -(Ex left, Ex right) { return new Ex(Expression.Subtract(left, right)); } public static Ex operator *(Ex left, Ex right) { return new Ex(Expression.Multiply(left, right)); } public static Ex operator /(Ex left, Ex right) { return new Ex(Expression.Divide(left, right)); } } 

So here is what I want to do:

 { ... Ex x = "x"; Ex y = 10.0; Ex z = x + y; LambdaExpression lambda = BuildLambda(z); Func<double,double> f = (Func<double,double>)lambda.Compile(); // f(5) = 15 } 

But how do I cross the tree propely and build my lambda (or delegates)

  LambdaExpression BuildLambda(Expression e) { ConstantExpression cex = e as ConstantExpression; if(cex != null) { return Expression.Lambda<Func<double>>( cex ); } ParameterExpression pex = e as ParameterExpression; if (pex != null) { Func<Expression, Expression> f = (x) => x; Expression body = f(pex); return Expression.Lambda<Func<double, double>>( body , pex); } BinaryExpression bex = e as BinaryExpression; if (bex != null) { LambdaExpression left = GetLambda(bex.Left); LambdaExpression rght = GetLambda(bex.Right); // Now what? } return null; } 

I tried several things to convert BinaryExpression bex to lambda, and all were still unavailable. I would like some tips and tricks. Note that the operands of the operation can be other objects of the expression, and only on the leaves of the tree will they be either ParameterExpression or ConstantExpression .

Thanks.

+4
source share
2 answers

You can create an Expression Tree when invoking conversion operators:

 public class Ex { private readonly Expression expr; public Ex(Expression expr) { this.expr= expr; } public Expression Expression { get { return this.expr; } } public static Ex operator +(Ex left, Ex right) { return new Ex(Expression.Add(left.expr, right.expr)); } ↑ ↑ // etc. } 

At each step, you unpack Expression from the Ex instance, use the Expression.* Method, and wrap the result in a new Ex instance.

In the end, all you have to do is extract Expression from the final Ex instance:

 Ex x = new Ex(Expression.Parameter(typeof(double), "x")); Ex y = new Ex(Expression.Constant(10.0, typeof(double))); Ex z = x + y; Expression<Func<double, double>> result = Expression.Lambda<Func<double, double>>(z.Expression, x.Expression); 

Note that the C # compiler provides a function to create an expression tree for you:

 Expression<Func<double, double>> result = x => x + 10.0; 

creates exactly the same expression tree as the code above.

+6
source

If your expressions are derived from a common class, look at the Visitor pattern in Gamma et al. This is even an example that they use.

0
source

All Articles