Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between HtmlHelper methods for accessing properties from lambda expression

I am trying to write my first customer Html Helper extension method following the format

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

And there seem to be several different ways to access the property name and value from the 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);

and

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

and also

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

Can somebody explain the difference between these methods? Are there any situations where one is superior to the others?

like image 299
ste-fu Avatar asked Apr 15 '15 21:04

ste-fu


1 Answers

These are 3 different ways of utilizing Expression<Func<TModel, TProperty>>. They will all give access to property value. They vary in access to the rest of the expression tree and process cost/efficiency.

Using expression.Compile().Invoke(model) executes the expression like a function on your model :: ( u => u.name).

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

You will get back a property or list<property>. It is most efficient when you simply want to execute the Expression and move on.


ModelMetadata.FromLambdaExpression uses an expression of type Expression<Func<TParameter, TValue>> as a DataDictionary lookup.

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

This approach is more verbose and less efficient, but you have access to property value and name.

Note that ModelMetadata also gives you access to the model's annotated values such as Validators and DisplayName.


MemberExpression uses an expression to access a field / property and it's type.

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

This approach is the most verbose and least efficient, but you get have value, name and property type.

MemberExpression.Member property give access to CustomAttributes

like image 165
Dave Alperovich Avatar answered Oct 31 '22 22:10

Dave Alperovich