BinaryExpression到Lambda

ja7*_*a72 4 c# lambda expression-trees

这可能是一些人所熟悉的.我有一个包装类Ex,它用一堆隐式转换和运算符包装表达式树.这是简化版

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

所以这就是我想要做的:

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

}
Run Code Online (Sandbox Code Playgroud)

但是我如何正确地横向树并建立我的lambda(或代表)

    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;
    }
Run Code Online (Sandbox Code Playgroud)

我已经尝试了几种方法来将BinaryExpressionbex转换为lambda,到目前为止所有这些都是不成功的.我想要一些建议和指示.请注意,操作的操作数可能是其他表达式对象,并且只在树的叶子上它们将是ParameterExpressionConstantExpression.

谢谢.

dtb*_*dtb 6

您可以在调用转换运算符时创建表达式树:

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.
}
Run Code Online (Sandbox Code Playgroud)

在每个步骤中,您ExpressionEx实例中"解压缩" ,应用Expression.*方法,并将结果包装在新Ex实例中.

最后,您所要做的就是Expression从最终Ex实例中提取:

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);
Run Code Online (Sandbox Code Playgroud)

请注意,C#编译器提供了为您创建表达式树的功能:

Expression<Func<double, double>> result = x => x + 10.0;
Run Code Online (Sandbox Code Playgroud)

创建与上面的代码完全相同的表达式树.