使用不同参数

时间:2016-04-08 13:41:09

标签: c# linq

我不知道是否有一种简单的方法来实现我的目标。 一方面,我有一个以编程方式建立的表达式,另一方面是手动输入的相同表达式。假设它们完全相同,我需要在手册中更改为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

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

enter image description here

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

//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)
}

我是否遗漏了一些简化过程的内容?

1 个答案:

答案 0 :(得分:1)

如果我说得对,你需要和use Expression<Func<T,X>> 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);
    }
}