2013-05-14 12 views
5

Come faccio a generare un espressione in grado di soddisfare il seguente obiettivo:dinamicamente valutando una stringa di proprietà con le espressioni

public object Eval(object rootObj, string propertyString)

esempio: Eval(person, "Address.ZipCode") => return person.Address.ZipCode

Expression.PropertyOrField non funziona perché ho don' t avere il tipo di ogni proprietà intermedia. Mi piacerebbe evitare di creare una dipendenza da una libreria di scripting.

Voglio provare a utilizzare le espressioni perché mi consentirebbe di memorizzare una cache di questi alberi di espressioni come sarebbero eseguiti più volte. Sono consapevole che è possibile farlo in modo iterativo o ricorsivo con la riflessione.

+0

Suppongo che Roslyn sia fuori dal tavolo? –

risposta

10

Sembra che tu stia cercando qualcosa di simile:

public object Eval(object root, string propertyString) 
{ 
    var propertyNames = propertyString.Split('.'); 
    foreach(var prop in propertyNames) 
    { 
     var property = root.GetType().GetProperty(prop); 
     if (property == null) 
     { 
      throw new Exception(...); 
     } 

     root = property.GetValue(root, null); 
    } 

    return root; 
} 

Per creare un Expression uso questo:

public Expression Eval(object root, string propertyString) 
{ 
    var propertyNames = propertyString.Split('.'); 
    ParameterExpression param = Expression.Parameter(root.GetType, "_"); 
    Expression property = param; 
    foreach(var prop in propertyName) 
    { 
     property = Expression.PropertyOrField(property, prop); 
    } 

    return Expression.Lambda(property, param); 
} 
+0

+1 - Stavo lavorando su qualcosa come questo, ma mi hai battuto su di esso. – Bobson

+0

Questo non funzionerebbe, poiché nell'esempio 'Person.Address.Zipcode' ha l'oggetto radice' Persona', che non ha 'Zipcode' come proprietà - questa è una proprietà della classe/struct' Indirizzo'. Quindi penso che la valutazione ricorsiva sia necessaria. –

+2

@JohnWillemse - le modifiche di 'root' su ogni iterazione, quindi nel secondo passaggio, si vedrebbe' Address' per 'Zipcode'. – Bobson

3

Ecco una versione ricorsiva di codice di pswg, lavorando con Expressions .

public Expression Eval(Expression expression, string property) 
{ 
    var split = property.Split('.'); 
    if (split.Length == 1) 
    { 
     return Expression.PropertyOrField(expression, property); 
    } 
    else 
    { 
     return Eval(Expression.PropertyOrField(expression, split[0]), property.Replace(split[0] + ".", "")); 
    } 
} 
+0

+1 Ma non penso che sia necessario dividere la stringa ogni volta se si utilizza la ricorsione. Puoi semplicemente usare 'property.IndexOf ('.')' E 'property.Substring (...)' –

+0

@ p.s.w.g - Completamente vero, e un modo migliore per farlo. Ero solo pigro. – Bobson

Problemi correlati