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