首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >表达式树-替换表达式

表达式树-替换表达式
EN

Stack Overflow用户
提问于 2017-07-05 18:59:29
回答 1查看 183关注 0票数 4

考虑两个表达式树:

代码语言:javascript
复制
Expression<Func<float, float, float>> f1 = (x, y) => x + y;
Expression<Func<float, float>> f2 = x => x * x;

我想替换表达式f2作为f1的第二个参数,并获得以下表达式:

代码语言:javascript
复制
Expression<Func<float, float, float>> f3 = (x, y) => x + y * y;

最简单的方法是使用Expression.LambdaExpression.Invoke,但结果将如下所示

代码语言:javascript
复制
(x, y) => f1(x, f2(y))

但这对我来说是不可接受的,因为ORM限制不能正确处理invoke/lambda。

有没有可能在不完全遍历表达式树的情况下构造表达式?一个可以满足我需求的工作示例可以在here中找到,但我想要更简单的解决方案。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-07-05 19:28:50

如果不完全遍历这两个表达式,则无法执行此操作。幸运的是,ExpressionVisitor使完整的遍历变得非常容易:

代码语言:javascript
复制
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;
    }
}

使用此访问者两次以完成替换:

代码语言:javascript
复制
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);

上面的照片

代码语言:javascript
复制
(x, y) => (x + (y * y))

Demo.

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44924390

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档