2

I don't know if there is an easy way to achieve my goal. On one side I have an Expression built up programmatically and on the other side the same expression inputted manually. Assuming their exactly the same, I need to change to ParameterExpression in the manual one to that is equal to the other. Here is a sample code

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

I paste also a debugger view image

enter image description here

Do you think this is doable? I started to draft this, but it appears to be a never-ending effort

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

Am I missing something to simplify the process?

1 Answers1

1

If i get you right, you need to do exactly the same as the answer here use Expression<Func<T,X>> in Linq contains extension

Edit

In that case, there were two different expression and the replacement was from Parameter to Expression. Here there is only one starting Expression and also the replacement is from Parameter to Parameter. The following code seems to work fine.

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);

and the visitor

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);
    }
}
Community
  • 1
  • 1
Petr Vávro
  • 1,506
  • 1
  • 10
  • 12
  • I've edited your answer to explain the different situation in my case and I've included the modified code. –  Apr 08 '16 at 14:52
  • Wasn't sure whether you are really replacing a parameter with a parameter, so couldn't show you a specific solution, glad the link helped you. – Petr Vávro Apr 08 '16 at 15:31