C#-表达式树-替代表达式
作者:互联网
考虑两个表达式树:
Expression<Func<float, float, float>> f1 = (x, y) => x + y;
Expression<Func<float, float>> f2 = x => x * x;
我想将表达式f2替换为f1的第二个参数,并获得以下表达式:
Expression<Func<float, float, float>> f3 = (x, y) => x + y * y;
最简单的方法是使用Expression.Lambda和Expression.Invoke,但是结果看起来像
(x, y) => f1(x, f2(y))
但是由于ORM限制无法正确处理invoke / lambda,这对我来说是不可接受的.
是否可以在不完全遍历表达式树的情况下构造表达式?可以找到一个满足我的需求的工作示例here,但我需要更简单的解决方案.
解决方法:
如果不完全遍历两个表达式,就无法做到这一点.幸运的是,ExpressionVisitor使完全遍历变得非常容易:
class ReplaceParameter : ExpressionVisitor {
private readonly Expression replacement;
private readonly ParameterExpression parameter;
public ReplaceParameter(
ParameterExpression parameter
, Expression replacement
) {
this.replacement = replacement;
this.parameter = parameter;
}
protected override Expression VisitParameter(ParameterExpression node) {
return node == parameter ? replacement : node;
}
}
使用此访客两次来完成替换:
Expression<Func<float,float,float>> f1 = (x, y) => x + y;
Expression<Func<float,float>> f2 = x => x * x;
var pX = f2.Parameters[0];
var pY = f1.Parameters[1];
var replacerF2 = new ReplaceParameter(pX, pY);
var replacerF1 = new ReplaceParameter(pY, replacerF2.Visit(f2.Body));
var modifiedF1 = Expression.Lambda(
replacerF1.Visit(f1.Body)
, f1.Parameters
);
Console.WriteLine(modifiedF1);
以上印刷品
(x, y) => (x + (y * y))
标签:c,expression-trees 来源: https://codeday.me/bug/20191111/2018183.html