views:

75

answers:

2

This may be familiar to some. I have a wrapper class Ex that wraps an expression tree with a bunch of implicit conversions and operators. Here is 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 to I transverse the tree propely and build my lambda's (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 tried several things to get to convert the BinaryExpression bex into a lambda, and all have been unsucessful up to now. I'd like some suggestions and pointers. Note that the operands of the operation might be other expression objects and only at the leafs of the tree they will either be ParameterExpression or ConstantExpression.

Thanks.

+3  A: 

You can create the Expression Tree as you call the 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" the Expression from the Ex instance(s), apply the Expression.* method, and wrap the result in a new Ex instance.

At the end, all you have to do is extract the 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 the feature 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.

dtb
Creating the trees is not the problem. My `Ex x = "x"` works just fine. Creating the delegates was solved with `Ex x = "x"; Ex y = 10.0; Ex z = x + y; Expression<Func<double, double>> lambda = Expression.Lambda<Func<double, double>>((Expression) z, (ParameterExpression) (Expression) x); Func<double, double> f3 = (Func<double, double>)lambda.Compile(); double result = f3(5); // result = 15` So thank you very much. The trick is to just do it and let the compiler figure out the details.
jalexiou
Do you have a reference/example/tutorial that deals specifically with building expression trees from code and then compiling into delegates? The next step is to extend this to method/function calls in addition to the simple arithmetics done above.
jalexiou
@jalexiou: I think your Ex class might be superfluous -- you seem to replicate a lot of function that is already there. If you want to dynamically define expression trees, you can use the Expression.* methods. If you want to statically define expression trees, the C# compiler can generate them for you. If all you need is a static lambda expression, you don't need expression trees at all. What are you trying to do?
dtb
A: 

If your expressions all derive from a common class, look up the "Visitor" pattern in Gamma, et al. This is even the example they use.

Zachary Vance
`System.Linq.Expressions.ExpressionVisitor` is an internal class and I cannot inherit from it.
jalexiou
@jalexiou: System.Linq.Expressions.ExpressionVisitor was made public in .NET 4.0. http://msdn.microsoft.com/en-us/library/system.linq.expressions.expressionvisitor.aspx
dtb