2016-04-08 8 views
1

Ich weiß nicht, ob es einen einfachen Weg gibt, um mein Ziel zu erreichen. Auf der einen Seite habe ich einen Ausdruck programmgesteuert und auf der anderen Seite den gleichen Ausdruck manuell eingegeben. Unter der Annahme, dass sie genau die gleichen sind, muss ich zu ParameterExpression in der manuellen Eins zu ändern, die gleich der anderen ist. Hier ist ein BeispielcodeKonvertieren/Klonen eines Lambda-Ausdrucks in einen anderen mit einem anderen Parameter

//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 fügen auch einen Debugger Ansicht Bild

enter image description here

Glauben Sie, das ist machbar? Ich begann diese zu entwerfen, aber es scheint eine zu sein, nie endende Anstrengung

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

Ich bin etwas fehlt, den Prozess zu vereinfachen?

Antwort

1

Wenn ich Sie richtig, Sie müssen die als Antwort gleiche tun genau hier use Expression<Func<T,X>> in Linq contains extension

bearbeiten

In diesem Fall gab es zwei unterschiedliche Expression und der Austausch war von Parameter zu Expression . Hier gibt es nur einen Anfangsausdruck und auch die Ersetzung erfolgt von Parameter zu Parameter. Der folgende Code scheint zu funktionieren.

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

und der Besucher

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); 
    } 
} 
+0

Ich habe bearbeitet die Antwort der unterschiedlichen Situation in meinem Fall zu erklären, und ich habe den geänderten Code enthalten. –

+0

War nicht sicher, ob Sie wirklich einen Parameter durch einen Parameter ersetzen, also konnte Ihnen keine spezifische Lösung zeigen, froh, dass der Link Ihnen half. –

Verwandte Themen