C# Lambda的二进制表达式
有些人可能对此很熟悉。我有一个包装类C# Lambda的二进制表达式,c#,lambda,expression-trees,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
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
}
{。。。
Ex x=“x”;
exy=10.0;
exz=x+y;
LambdaExpression lambda=BuildLambda(z);
Func f=(Func)lambda.Compile();
//f(5)=15
}
但是如何正确地横切树并构建lambda(或委托)
LambdaExpression BuildLambda(表达式e)
{
恒压cex=e,表示恒压;
如果(cex!=null)
{
返回表达式.Lambda(cex);
}
ParameterExpression pex=e作为ParameterExpression;
如果(pex!=null)
{
Func f=(x)=>x;
表达体=f(pex);
返回表达式.Lambda(body,pex);
}
二进制表达式bex=e作为二进制表达式;
如果(bex!=null)
{
LambdaExpression left=GetLambda(bex.left);
LambdaExpression rght=GetLambda(bex.Right);
//现在怎么办?
}
返回null;
}
我尝试了几种方法将BinaryExpression
bex转换成lambda,但到目前为止都没有成功。我想要一些建议和建议。请注意,该操作的操作数可能是其他表达式对象,并且仅在树的叶子处,它们将是ParameterExpression
或ConstantExpression
谢谢。您可以在调用转换运算符时创建表达式树:
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
实例中“解包”表达式,应用表达式。*
方法,并将结果包装到新的Ex
实例中
最后,您只需从最后的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);
exx=newex(表达式参数(typeof(double),“x”);
exy=新的Ex(表达式常数(10.0,typeof(double));
exz=x+y;
表达结果=
Lambda(z.表达式,x.表达式);
请注意,C#编译器提供了为您创建表达式树的功能:
Expression<Func<double, double>> result = x => x + 10.0;
表达式结果=x=>x+10.0;
创建与上述代码完全相同的表达式树。如果您的表达式都来自一个公共类,请在Gamma等中查找“访问者”模式。这甚至是他们使用的示例。创建树不是问题。我的Ex x=“x”
工作正常。使用Ex x=“x”解决了代理的创建问题;exy=10.0;exz=x+y;表达式lambda=Expression.lambda((表达式)z,(参数表达式)(表达式)x);Func f3=(Func)lambda.Compile();双重结果=f3(5);//结果=15
非常感谢。诀窍就是这样做,让编译器了解细节。你有没有一个参考/示例/教程专门介绍如何从代码构建表达式树,然后编译为委托?下一步是将其扩展到方法/函数调用,以及上面所做的简单算术。@jalexiou:我认为您的Ex类可能是多余的——您似乎复制了很多已经存在的函数。如果要动态定义表达式树,可以使用expression.*方法。如果您想静态定义表达式树,C#编译器可以为您生成它们。如果只需要一个静态lambda表达式,则根本不需要表达式树。你想做什么?System.Linq.Expressions.ExpressionVisitor
是一个内部类,我无法从中继承。@jalexiou:System.Linq.Expressions.ExpressionVisitor已在.NET 4.0中公开。
Expression<Func<double, double>> result = x => x + 10.0;