람다에 이진 표현

c# expression-trees lambda

문제

이것은 일부 사람들에게는 친숙 할 수 있습니다. 나는 표현식 트리를 암시적인 변환과 연산자로 묶는 래퍼 클래스 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));
    }
}

그래서 여기에 내가하고 싶은 것이있다.

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

}

그러나 나는 나무를 예리하게 가로 지르고 나의 람다 (또는 대표자)

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

BinaryExpression lambda로 변환하기 위해 여러 가지 시도를했으며, 지금까지는 모든 것이 실패했습니다. 나는 몇 가지 제안과 조언을 원한다. 연산의 피연산자는 다른 표현식 객체 일 수 있으며 트리의 리프에서만 ParameterExpression 또는 ConstantExpression 이 될 수 있습니다.

감사.

수락 된 답변

변환 연산자를 호출 할 때 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.
}

각 단계에서 Ex 인스턴스의 Expression 을 "압축 해제"하고 Expression.* 메서드를 적용한 다음 새 Ex 인스턴스에 결과를 래핑합니다.

결국, 최종 Ex 인스턴스에서 Expression 을 추출하면됩니다.

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);

C # 컴파일러는 표현 트리를 생성하는 기능을 제공합니다.

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

위의 코드와 정확히 같은 표현식 트리를 만듭니다.


인기 답변

표현식이 모두 공통 클래스에서 파생 된 경우 감마 (Gamma) 등의 "방문자 (Visitor)"패턴을 찾으십시오. 이것은 심지어 그들이 사용하는 예입니다.



아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.