【问题标题】:Convert/Clone a Lambda Expression into another with a different parameter将 Lambda 表达式转换/克隆为另一个具有不同参数的表达式
【发布时间】:2016-04-08 23:29:57
【问题描述】:

我不知道是否有一种简单的方法可以实现我的目标。 一方面,我以编程方式建立了一个表达式,另一方面,我手动输入了相同的表达式。假设它们完全相同,我需要将手册中的 ParameterExpression 更改为等于另一个。 这是一个示例代码

//I have this expression (for example)
Expression<Func<Bar,bool>> old_expr = x => x.Name == x.ColBar;
//I want to change parameter from x to y
//I already have the y parameter in the code, let's say it is the following
ParameterExpression py = Expression.Parameter(typeof(Bar), "y");
//this is what I have tried, but it is *not* complete neither generic
Expression expr_to_do;
if (old_expr.Body.NodeType.Equals(ExpressionType.Convert)) {
    UnaryExpression convEx = old_expr.Body as UnaryExpression;
    expr_to_do = convEx.Operand;
} else {
    expr_to_do  = old_expr.Body;
}
//TODO: convert the BinarayExpression eqEx, etc... etc...
var newLambda = Expression.Lambda(expr_to_do, new ParameterExpression[1]{py});

//Again, what I want to get is the following, where y *is* the parameter defined *above* 
Expression<Func<Bar,bool>> new_expr = y => y.Name == y.ColBar;
//The code/method I'm looking for - if it does exist a method to do that - must be generic enough not specific to this single expression

我还粘贴了一个调试器视图图像

你认为这是可行的吗? 我开始起草这个,但它似乎是一个永无止境的努力

//TODO convert the BinarayExpression eqEx, etc... etc...

if (expr_to_do.NodeType.Equals(ExpressionType.Equal)) {
    // have I to manage each Expr Type case??
    var eqExpr = expr_to_do as BinaryExpression;
    var left = eqExpr.Left as MemberExpression;
    ...
    var new_left = Expression.Property(...,py)
}

我是否遗漏了什么来简化流程?

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    如果我猜对了,你需要和这里的答案完全相同use Expression&lt;Func&lt;T,X&gt;&gt; in Linq contains extension

    编辑

    在那种情况下,有两个不同的表达式,替换是从参数到表达式。这里只有一个起始表达式,并且替换是从参数到参数。 以下代码似乎可以正常工作。

    var map = old_expr.Parameters.ToDictionary(p => p, p => py);
    var reboundBody = ParameterRebinder.ReplaceParameters(map, old_expr.Body);
    var lambda = Expression.Lambda<Func<Bar,bool>>(reboundBody, py);
    

    和访客

    public class ParameterRebinder : ExpressionVisitor
    {
        private readonly Dictionary<ParameterExpression, ParameterExpression> Map;
    
        public ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
        {
            this.Map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
        }
    
        public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
        {
            return new ParameterRebinder(map).Visit(exp);
        }
    
        protected override Expression VisitParameter(ParameterExpression node)
        {
            ParameterExpression replacement;
            if (this.Map.TryGetValue(node, out replacement))
            {
                return replacement;
                //return this.Visit(replacement);
            }
            return base.VisitParameter(node);
        }
    }
    

    【讨论】:

    • 我已经编辑了您的答案以解释我的情况的不同情况,并且我已经包含了修改后的代码。
    • 不确定您是否真的用参数替换参数,因此无法向您展示具体的解决方案,很高兴该链接对您有所帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多