模型属性显示名称使用反射

时间:2014-03-27 11:02:48

标签: c# asp.net-mvc-4 razor reflection html-helper

我正在开发一个项目,我需要在屏幕上输出几百个属性。为了节省很多繁琐的标记,我决定使用反射。

//markup removed to keep this concise
@for (var i = 0; i < Model.SiteAndJobDetails.GetType().GetProperties().Count(); i++)
{
  @Model.SiteAndJobDetails.GetType().GetProperties()[i].Name
  @Model.SiteAndJobDetails.GetType().GetProperties()[i].GetValue(Model.SiteAndJobDetails, null)
}

虽然呈现速度较慢,但​​这将节省我用HTML助手写出大约200个属性和值。至少,这是计划。但是,我需要使用@Html.DisplayNameFor或类似内容来从属性中获取Display属性值。

我的初步想法是

@Html.DisplayNameFor(m=>@Model.SiteAndJobDetails.GetType().GetProperties()[i].Name)

但这不起作用,我想是因为我在这里使用反射来获取属性名称。还有另一种方式吗?

4 个答案:

答案 0 :(得分:1)

您可以使用元数据(框架的功能)来获取它:

string displayName = ViewData.ModelMetadata.Properties
      .Where(x => x.PropertyName == Model.SiteAndJobDetails.GetType()
                                   .GetProperties()[i].Name)
      .SingleOrDefault()
      .DisplayName;

答案 1 :(得分:1)

@Andrei使用ViewData.ModelMetadata是正确的,但语法略有偏差。正确的语法是

@ViewData.ModelMetadata.Properties.First(x => x.PropertyName == "SiteAndJobDetails")
.Properties.SingleOrDefault(x => x.PropertyName == Model.SiteAndJobDetails.GetType().GetProperties()[i].Name)
.DisplayName

最终解决方案是检查属性是否存在,是否确实使用它,否则使用属性名称

@if (!string.IsNullOrEmpty(@ViewData.ModelMetadata.Properties.First(x => x.PropertyName == "SiteAndJobDetails").Properties.SingleOrDefault(x => x.PropertyName == Model.SiteAndJobDetails.GetType().GetProperties()[i].Name).DisplayName))
{
    @ViewData.ModelMetadata.Properties.First(x => x.PropertyName == "SiteAndJobDetails").Properties.SingleOrDefault(x => x.PropertyName == Model.SiteAndJobDetails.GetType().GetProperties()[i].Name).DisplayName
}
else
{
    @Model.SiteAndJobDetails.GetType().GetProperties()[i].Name
}

答案 2 :(得分:0)

或者,将其添加到剃须刀中:

@functions {
string R<TCLASS>(Expression<Func<TCLASS, Object>> expression) //Lambda = x => x.TPROPERTY
{
    var memberExpression = expression.Body as MemberExpression;
    if(memberExpression == null)
    {
        memberExpression = (MemberExpression) ((UnaryExpression)expression.Body).Operand;
    }

    return memberExpression.Member.Name;
}
}

然后你可以:

@(R<ModelClassName>(x => x.PropertyName)) //Outputs "PropertyName"

我喜欢在编写接收JSON的JavaScript时使用它。它可以让你这样做:

<script>
    function recieveJsonResult(classNameDto) {
        var classProperty = classNameDto.@(R<ClassNameDto>(x => x.PropertyName));
    }
</script>

通过这种方式,您可以在lambda中获得自动完成功能,并且您可以自由重命名该属性,而无需担心破坏前端代码。

答案 3 :(得分:0)

我更喜欢这个答案:https://stackoverflow.com/a/31448493/9266796

已更新为今天的语法:

var displayName = property.GetCustomAttribute<DisplayAttribute>().Name;

或者实际上这更容易:https://stackoverflow.com/a/19940277/9266796

@Html.Label(property.Name);