2016-06-17 2 views
2

Si je classe simpleComment analyser simple capture l'expression de fermeture et obtenir l'objet cible et sélecteur

class Foo { 
    int Value { get; set; } = 20 
} 

class Bar { 
    Foo foo { get; set;} = new Foo(); 
} 

puis j'écris une expression de sélection

var bar = new Bar(); 
Expression<Func<int>> fn =() => bar.foo.Value; 

Je sais que si je de type

var v = fn.Compile()() 

v sera égale à démontrant que la fermeture est en effet capturée. Je déduis que dans l'expression une référence à la cible capturée de l'expression est stockée. J'aimerais que cela sorte de l'expression.

Par exemple

Bar capturedBar = GetTarget(fn); 
Assert(capturedBar == bar); 

et une autre fonction

string selector = GetSelector(fn) 

qui doit retourner

"bar.foo.A" 

Répondre

2

Vous pouvez accomplir cette tâche avec l'aide de la technique Expression Visitor.

Voici la démonstration simple et sale de l'idée principale:

var bar = new Bar(); 
Expression<Func<int>> fn =() => bar.foo.Value; 

BarExtractor be = new BarExtractor(); 
be.Visit(fn); 
Bar capturedBar = be.bar; 

La classe BarExtractor est déclarée comme suit:

class BarExtractor : ExpressionVisitor { 
    public Bar bar; 
    protected override Expression VisitConstant(ConstantExpression node) { 
     object closureObj = node.Value; 
     if(closureObj != null && closureObj.GetType().Name.StartsWith("<>c__DisplayClass")) { 
      var barField = closureObj.GetType().GetField("bar"); 
      if(barField != null && barField.FieldType == typeof(Bar)) 
       bar = barField.GetValue(closureObj) as Bar; 
     } 
     return base.VisitConstant(node); 
    } 
}