Разница между методами HtmlHelper для доступа к свойствам из лямбда-выражения

Я пытаюсь написать свой первый метод расширения Html Helper, следуя формату

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

И, похоже, существует несколько способов доступа к имени и значению свойств из 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);

и

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

а также

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

Может кто-нибудь объяснить разницу между этими методами? Есть ли ситуации, когда один превосходит других?

Ответ 1

Это три разных способа использования Expression<Func<TModel, TProperty>>. Они все предоставят доступ к стоимости имущества. Они различаются по доступу к остальной части дерева выражений и стоимости/эффективности процесса.

Использование expression.Compile().Invoke(model) выполняет выражение как функцию на вашей модели:: ( u => u.name).

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

Вы вернете свойство или list<property>. Это наиболее эффективно, когда вы просто хотите выполнить Expression и двигаться дальше.


ModelMetadata.FromLambdaExpression использует выражение типа Expression<Func<TParameter, TValue>> как поиск DataDictionary.

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

Этот подход более подробный и менее эффективный, но у вас есть доступ к свойству значение и name.

Обратите внимание, что ModelMetadata также дает вам доступ к аннотированным значениям модели, таким как Validators и DisplayName.


MemberExpression использует выражение для доступа к полю/свойству и его тип.

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

Этот подход является наиболее подробным и наименее эффективным, но у вас есть значение, имя и тип свойства.

Свойство MemberExpression.Member предоставляет доступ к CustomAttributes