2011-04-05 14 views
14

Per semplicità, immaginate il seguente codice:Come ottengo il valore da un'espressione anonima?

Voglio creare un Foo:

public class Foo 
{ 
    public string Bar { get; set; } 
} 

e passarlo a uno speciale metodo di Html Helper:

Html.SomeFunction(f => f.Bar); 

che è definita come:

public string SomeFunction<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) 

Voglio ottenere il valore di Bar all'interno di questa funzione, ma non ho assolutamente idea di come ottenerlo.

risposta

26

Basta compilare l'espressione e ottenere il valore.

Func<TModel, TValue> method = expression.Compile(); 

TValue value = method(html.ViewData.Model); 
// might be a slightly different property, but you can get the ViewModel 
// from the HtmlHelper object. 
+0

Viene visualizzato il seguente errore con il codice: Errore 'System.Web.Mvc.HtmlHelper ' non contiene una definizione per 'Modello' e non metodo di estensione 'Modello' che accetta un primo argomento di tipo 'System.Web.Mvc.HtmlHelper ' potrebbe essere trovato (ti manca una direttiva using o un riferimento di assembly?) – mynameiscoffey

+2

Dovrebbe essere 'html.ViewData.Model'. Il mio post iniziale era semplicemente in fretta con il nome della proprietà. – Tejs

+0

+1 Funziona come un incanto, grazie !! – mynameiscoffey

5

È necessario chiamare Compile() nell'espressione per ottenere Func e quindi eseguirlo.

public string SomeFunction<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) 
{ 
    TValue valueOfBar = expression.Compile()(html.Model); // Assumes Model is accessible from html. 

    // Do stuff 
} 

Nota a margine: se non v'è alcuna necessità per le espressioni dinamiche o analisi di espressione si potrebbe anche passare il Func direttamente al posto.

+1

+1 reddog parla anche la verità qui; se in realtà non vi è alcun motivo per esaminare l'espressione, il semplice passaggio di "Func " è molto meglio. – Tejs

+1

Sfortunatamente l'espressione è necessaria per altre interazioni che avvengono all'interno del metodo – mynameiscoffey

0

Per coloro che utilizzano espressione senza MVT modello, si otterrebbe nome e il valore dei beni in un modo seguente.

public static string Meth<T>(Expression<Func<T>> expression) 
{ 
    var name = ((MemberExpression)expression.Body).Member.Name; 
    var value = expression.Compile()(); 
    return string.Format("{0} - {1}", name, value); 
} 

uso:

Meth(() => YourObject.Property); 
0

Utilizzando Compile() utilizzerà il compilatore-quadro Roslyn e emetterà MSIL-codice che sarà caricato in modo dinamico nella vostra applicazione. Questo codice eseguibile occupa la memoria e, in contrasto con la memoria "normale", non è soggetto alla garbage collection né è possibile liberarlo da soli. Se lo fai troppo frequentemente (come regolarmente durante la generazione SQL) alla fine avrai esaurito la memoria. Mi sono imbattuto in questo problema e open-source le mie soluzioni come una libreria open-source:

https://www.nuget.org/packages/MiaPlaza.ExpressionUtils

Problemi correlati