用于从lambda表达式访问属性的HtmlHelper方法之间的区别

时间:2015-04-15 21:18:01

标签: c# asp.net-mvc razor reflection lambda

我正在尝试按照格式

编写我的第一个客户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 个答案:

答案 0 :(得分:10)

这是使用Expression<Func<TModel, TProperty>>的3种不同方式。他们都将获得财产价值。它们在访问表达树的其余部分和处理成本/效率方面各不相同。

使用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;

此方法更详细,效率更低,但您可以访问属性名称

请注意,ModelMetadata还允许您访问模型的带注释值,例如验证程序 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