Lambda to BinaryExpression

c# expression-trees lambda

Question

Others may be acquainted with this. I take a lesson on wrappers.Ex It contains a number of implicit conversions and operators around an expression tree. Here is a shorter 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));
    }
}

Thus, this 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

}

However, how can I cross the tree propeller and construct my lambdas? (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 have made several attempts to persuade theBinaryExpression bex into a lambda, and all of them have failed so far. I want some advice and direction. Keep in mind that the operands of the operation might be other expression objects, and only at the tree's leaves will they eitherParameterExpression or ConstantExpression .

Thanks.

1
4
9/2/2010 12:20:15 PM

Accepted Answer

As you use the conversion operators, you may build the Expression Tree:

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

You "unpack" the steps at each one.Expression using theEx example(s), use theExpression.* Then enclose the outcome in a new technique.Ex instance.

All that is left to do is to extract theExpression from the lastEx 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);

You should be aware that the C# compiler has the option to build an Expression Tree for you:

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

precisely the same Expression Tree as the aforementioned code.

6
8/20/2010 8:05:56 PM

Popular Answer

Look up the "Visitor" pattern in Gamma, et al. if all of your phrases come from the same class. Even their example is similar to this.



Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow