Это может быть знакомо некоторым. У меня есть класс-оболочка Ex
, который обертывает дерево выражений кучей неявных преобразований и операторов. Вот упрощенная версияBinaryExpression to Lambda
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
}
Но как я пробежать дерево propely и построить мой лямбда (или делегатов)
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;
}
Я попробовал несколько вещей, чтобы преобразовать bex BinaryExpression
в лямбда, и до сих пор все были неаккуратными. Я бы хотел несколько советов и указаний. Обратите внимание, что операнды операции могут быть другими объектами выражения, и только у листьев дерева они будут либо ParameterExpression
, либо ConstantExpression
.
Спасибо.
Создание деревьев - не проблема. Мой 'Ex x =" x "' отлично работает. Создание делегатов было решено с помощью «Ex x =« x »; Ex y = 10,0; Ex z = x + y; Выражение> lambda = Expression.Lambda > ((выражение) z, (ParameterExpression) (выражение) x); Func f3 = (Func ) lambda.Compile(); двойной результат = f3 (5); // result = 15' Большое спасибо. Хитрость заключается в том, чтобы просто сделать это и дать компилятору выяснить детали. –
ja72
Есть ли у вас справочник/пример/учебник, посвященный особенностям построения деревьев выражений из кода, а затем компиляция в делегаты? Следующий шаг - расширить это на вызовы метода/функции в дополнение к простой арифметике, сделанной выше. – ja72
@ jalexiou: Я думаю, что ваш класс Ex может быть лишним - вы, похоже, копируете много функций, которые уже есть. Если вы хотите динамически определять деревья выражений, вы можете использовать методы Expression. *. Если вы хотите статически определять деревья выражений, компилятор C# может генерировать их для вас. Если все, что вам нужно, это статическое выражение лямбда, вам вообще не нужны деревья выражений. Что ты пытаешься сделать? – dtb