2015-04-15 4 views
11

Sto cercando di scrivere il mio primo cliente metodo di estensione Html Helper seguendo il formatodifferenza tra i metodi HtmlHelper per l'accesso a oggetti di espressione lambda

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

E sembra che ci siano diversi modi per accedere al nome della proprietà e il valore dal 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); 

e

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

e anche

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

Qualcuno può spiegare la differenza tra questi metodi? Ci sono situazioni in cui uno è superiore agli altri?

+0

Se si controlla il [codice sorgente MVC] (http://aspnetwebstack.codeplex.com/SourceControl/latest) per 'System.Web.Mvc.Html ', vedrai che tutti gli helper usano la seconda variante -' ModelMetadata.FromLambdaExpression (expression, html.ViewData); quindi, presumo che sia l'approccio migliore –

risposta

10

Questi sono 3 modi diversi di utilizzare Expression<Func<TModel, TProperty>>. Daranno tutti accesso al valore della proprietà. Variano l'accesso al resto dell'albero delle espressioni e processano i costi/l'efficienza.

L'utilizzo di expression.Compile().Invoke(model) esegue l'espressione come una funzione sul modello: (u => u.name).

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

verranno restituiti una proprietà o list<property>. È più efficiente quando vuoi semplicemente eseguire l'espressione e andare avanti.


ModelMetadata.FromLambdaExpression utilizza un'espressione di tipo Expression<Func<TParameter, TValue>> come una ricerca DataDictionary.

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

Questo approccio è più prolisso e meno efficiente, ma si ha accesso alla proprietà valore e nome.

noti che ModelMetadata dà anche accesso ai valori annotati del modello come Validatori e DisplayName.


MemberExpression utilizza un'espressione per accedere a un campo/proprietà e il suo tipo.

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

questo approccio è il più prolisso e meno efficiente, ma si ottiene avere valore, nome del tipo e proprietà.

MemberExpression.Member proprietà dare accesso a CustomAttributes