从导航属性获取元数据
本文关键字:元数据 获取 属性 导航 | 更新日期: 2023-09-27 18:09:47
我想知道是否有更好的方法来获得导航属性元数据值与ModelMetadataProviders
类的帮助?
cshtml示例:
@model IEnumerable<WebApp.Web.Service.OfficeService.PlayerDeposit>
<div id="pagedList">
<table class="table Report tablesorter table-bordered table">
<thead>
<tr>
<th class="table-head sortTable">@Html.DisplayColumnNameFor(Model, m=> m.PaymentProvider.Name)
</th>
<th class="table-head sortTable">@Html.DisplayColumnNameFor(Model, m=> m.Country.CountryName)
</th>
<th class="table-head sortTable">@Html.DisplayColumnNameFor(Model, m=> m.NumberOfPlayers)
</th>
<th class="table-head sortTable">@Html.DisplayColumnNameFor(Model, m=> m.AmountDeposited)
</th>
<th class="table-head sortTable">@Html.DisplayColumnNameFor(Model, m=> m.Collected)
</th>
<th class="table-head sortTable">@Html.DisplayColumnNameFor(Model, m=> m.TransactionFee)
</th>
<th class="table-head sortTable">Balance
</th>
<th></th>
</tr>
</thead>
因此,为了获得元数据名称,我必须使用ModelMetadataProviders
类创建视图助手。
我找不到直接的方法来访问提供的实体名的导航属性名,所以我不得不使用旧的字符串操作(我知道有点乱):
public static IHtmlString DisplayColumnNameFor<TModel, TClass, TProperty>
(this HtmlHelper<TModel> helper, IEnumerable<TClass> model,
Expression<Func<TClass, TProperty>> expression)
{
string entity = "";
string name = "";
ModelMetadata metadata = null;
var expressionText = ExpressionHelper.GetExpressionText(expression);
name = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(expressionText);
if (name.Contains('.'))
{
int indexOfDot = name.IndexOf('.');
entity = name.Substring(0, indexOfDot);
name = name.Substring(indexOfDot + 1, name.Length - (indexOfDot + 1));
Type classType = Type.GetType("WebApp.Web.Service.OfficeService." + entity);
metadata =
ModelMetadataProviders
.Current
.GetMetadataForProperty(() => Activator.CreateInstance(classType), classType, name);
}
else
{
metadata = ModelMetadataProviders.Current.GetMetadataForProperty(
() => Activator.CreateInstance<TClass>(), typeof(TClass), name);
}
return new MvcHtmlString(metadata.DisplayName);
}
正如你所看到的,因为我真的不知道是否有更好的方法来直接访问导航属性从表达式我首先分离实体和名称(我只计算一个层次的深度导航属性),然后在反射的帮助下,我得到了类类型,所以我可以访问实体元数据…
我尝试旧hack在html作为实例化PlayerDeposit,然后只是使用模型直接与@Html.DisplayNameFor
的html内,但由于某种原因它不允许我(含糊不清的错误):@Html.DisplayNameFor(model => model.Carriers.FirstOrDefault().Name)
.
我认为正确的做法是使用ModelMetadata.FromLambdaExpression
。重要的是要注意,对于这个应用程序,传递给FromLambdaExpression
的ViewDataDictionary
不会用于任何事情,因为我们不需要检查视图数据的值。我们从属性本身获取显示名。通过允许我们创建用于调用的正确类型的ViewDataDictionary
,使得它相对容易。
public static class HtmlHelperExtensions
{
public static IHtmlString DisplayColumnNameFor<TModel, TCollection, TProperty>(
this HtmlHelper<TModel> helper,
IEnumerable<TCollection> model,
Expression<Func<TCollection, TProperty>> expression)
{
if (expression == null)
{
throw new ArgumentNullException("expression");
}
var dictionary = new ViewDataDictionary<TCollection>();
var metadata = ModelMetadata.FromLambdaExpression(expression, dictionary);
return MvcHtmlString.Create(metadata.DisplayName);
}
}