2011-04-05 22 views
14

Dla uproszczenia wyobrazić następujący kod:Jak uzyskać wartość z anonimowego wyrażenia?

Chcę stworzyć Foo:

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

i przekazać je do specjalnego sposobu Html Helper:

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

który jest zdefiniowany jako:

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

Chcę uzyskać wartość paska wewnątrz tej funkcji, ale absolutnie nie mają pojęcia, jak ją zdobyć.

Odpowiedz

26

Po prostu skompiluj wyrażenie i uzyskaj wartość.

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

Otrzymuję następujący błąd z kodem: Błąd "System.Web.Mvc.HtmlHelper " nie zawiera definicji "Modelu" i nie ma metoda rozszerzenia "Model" akceptujący pierwszy argument typu "System.Web.Mvc.HtmlHelper " może być znaleziony (czy brakuje dyrektywy użycia lub odniesienia do zestawu?) – mynameiscoffey

+2

Powinien to być 'html.ViewData.Model'. Mój pierwszy wpis był po prostu w pośpiechu z nazwą nieruchomości. – Tejs

+0

+1 Działa jak czar, dzięki! – mynameiscoffey

5

Będziesz musiał zadzwonić pod numer Compile(), aby uzyskać Func, a następnie wykonać to.

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 
} 

Uwaga boczna: Jeśli nie ma potrzeby korzystania z wyrażeń dynamicznych lub analizy wyrażeń, można zamiast tego przekazać bezpośrednio funkcję Func.

+1

+1 Reddog również mówi prawdę tutaj; jeśli faktycznie nie ma powodu, aby badać wyrażenie, to po prostu przekazanie 'Func ' jest znacznie lepsze. – Tejs

+1

Niestety wyrażenie jest wymagane w przypadku innych interakcji zachodzących w ramach metody – mynameiscoffey

0

Dla tych, którzy używają wyrażenia bez modelu MVT, można uzyskać nazwę i wartość właściwości w następujący sposób.

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

zastosowanie:

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

Korzystanie Compile() użyje kompilator ramy Roslyn i wyemituje MSIL kod, który będzie dynamicznie ładowany do aplikacji. Ten kod wykonywalny zajmuje pamięć i, w przeciwieństwie do "normalnej" pamięci, nie podlega odśmiecaniu i nie można go uwolnić samodzielnie. Jeśli robisz to zbyt często (jak regularnie podczas generowania kodu SQL), w końcu skończy Ci się pamięć. Wpadłem na ten temat i na otwartym pochodzą moje rozwiązania jak biblioteki open-source:

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

Powiązane problemy