问题 用于从lambda表达式访问属性的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);

有人可以解释这些方法之间的区别吗?有没有一个优于其他人的情况?


1285
2018-04-15 21:18


起源

如果你检查一下 MVC源代码 对于 System.Web.Mvc.Html,你会看到帮助者都使用第二个变种 - ModelMetadata.FromLambdaExpression(expression, html.ViewData); 所以我认为这是更好的方法 - Stephen Muecke


答案:


这些是3种不同的利用方式 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;

这种方法更冗长,效率更低,但您可以访问财产  和 名称

注意 ModelMetadata  还可以访问模型的注释值,例如 验证器 和 显示名称


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


10
2018-04-20 19:16