2015-04-15 14 views
11

próbuję pisać mojego pierwszego klienta Html Helper metodę rozszerzenia po formacieRóżnice między metodami HtmlHelper dostępu do właściwości z lambda wyrażenia

public static MvcHtmlString<TModel, TProperty> 
    MyHelperFor(this HtmlHelper<TModel> helper, 
    Expression<Func<TModel, TProperty>> expression) 

I nie wydają się być kilka różnych sposobów, aby uzyskać dostęp do nazwy właściwości i wartości z expression

var body = expression.Body as MemberExpression; 
var propertyName = body.Member.Name; 
var propertyInfo = typeof(TModel).getProperty(propertyName) 
var propertyValue = propertyInfo.GetValue(helper.ViewData.Model); 

i

var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData); 
var propertyName = metadata.PropertyName; 
var propertyValue = metadata.Model; 

i także

TModel model = (TModel)helper.ViewContext.ViewData.ModelMetadata.Model; 
TProperty value = expression.Compile().Invoke(model); 

Czy ktoś może wyjaśnić różnicę między tymi metodami? Czy są sytuacje, w których jeden jest lepszy od innych?

+0

Jeśli skontrolować [kod źródłowy MVC] (http://aspnetwebstack.codeplex.com/SourceControl/latest) dla 'System.Web.Mvc.Html 'zobaczysz, że wszyscy pomocnicy używają drugiej odmiany -' ModelMetadata.FromLambdaExpression (expression, html.ViewData); 'tak zakładam, że to jest lepsze podejście –

Odpowiedz

10

Są to 3 różne sposoby wykorzystania Expression<Func<TModel, TProperty>>. Wszystkie dadzą dostęp do wartości nieruchomości. Różnią się dostępem do reszty drzewa wyrażeń i przetwarzają koszt/wydajność.

Użycie expression.Compile().Invoke(model) wykonuje wyrażenie podobne do funkcji w modelu :: (u => u.name).

TModel model = (TModel)helper.ViewContext.ViewData.ModelMetadata.Model; 
TProperty value = expression.Compile().Invoke(model); 

Otrzymasz z powrotem nieruchomość lub list<property>. Jest najskuteczniejszy, gdy chcesz po prostu wykonać Wyrażenie i przejść dalej.


ModelMetadata.FromLambdaExpression wykorzystuje ekspresji typu Expression<Func<TParameter, TValue>> jako DataDictionary odnośnika.

var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData); 
var propertyName = metadata.PropertyName; 
var propertyValue = metadata.Model; 

Takie podejście jest bardziej rozwlekły i mniej wydajne, ale masz dostęp do własności wartości i nazwa.

Zauważ, że ModelMetadata daje również dostęp do adnotacjami wartościami modelu takich jak Walidatory i displayname.


MemberExpression używa wyrażenia, aby uzyskać dostęp do pola/nieruchomość i jest to rodzaj.

var body = expression.Body as MemberExpression; 
var propertyName = body.Member.Name; 
var propertyInfo = typeof(TModel).getProperty(propertyName) 
var propertyValue = propertyInfo.GetValue(helper.ViewData.Model); 

Takie podejście jest najbardziej gadatliwym i najmniej skuteczny, ale masz mieć wartość, nazwa typu i nieruchomość.

MemberExpression.Member nieruchomość daje dostęp do CustomAttributes