MVC.net在视图中获取枚举显示名称,而不必引用视图中的枚举类型



我在ViewModelBase类中有以下helper方法,它由其他视图模型继承:

public string GetEnumName<T>(Enum value)
        {
            Type enumType = typeof(T);
            var enumValue = Enum.GetName(enumType, value);
            MemberInfo member = enumType.GetMember(enumValue)[0];
            var attrs = member.GetCustomAttributes(typeof(DisplayAttribute), false);
            var outString = ((DisplayAttribute)attrs[0]).Name;
            if (((DisplayAttribute)attrs[0]).ResourceType != null)
            {
                outString = ((DisplayAttribute)attrs[0]).GetName();
            }
            return outString;
        }

然后我从这样的角度称之为:

<p>
@{var rel = Model.GetEnumDisplayName<Enums.wheteverEnum>(Model.wheteverEnum); }
@rel
</p>

问题是,我能用这个方法吗?这样我就不必告诉它enum的类型了?基本上,我想为所有enum做这件事:

@Model.GetEnumDisplayName(Model.weeverEnum)

没有typeof,没有T,不需要在视图中添加对Enums命名空间的引用。。。

可能吗?

您可以简单地删除类型参数并使其成为扩展方法。

    public static string DisplayName(this Enum value)
    {
        Type enumType = value.GetType();
        var enumValue = Enum.GetName(enumType, value);
        MemberInfo member = enumType.GetMember(enumValue)[0];
        var attrs = member.GetCustomAttributes(typeof(DisplayAttribute), false);
        var outString = ((DisplayAttribute)attrs[0]).Name;
        if (((DisplayAttribute)attrs[0]).ResourceType != null)
        {
            outString = ((DisplayAttribute)attrs[0]).GetName();
        }
        return outString;
    }
    @Model.wheteverEnum.DisplayName()

你能不把它写成一个扩展方法吗?类似。。。

public static class EnumExtensions
{
  public static string ToDescription(this Enum e)
  {
     var attributes = (DisplayAttribute[])e.GetType().GetField(e.ToString()).GetCustomAttributes(typeof(DisplayAttribute), false);
     return attributes.Length > 0 ? attributes[0].Description : string.Empty;
  }
}

用法:

@Model.WhateverEnum.ToDescription();

干得好@jrummell!

我在下面添加了一个小调整,它捕捉了枚举没有关联的Display属性的场景(目前它抛出了一个异常)

/// <summary>
/// Gets the DataAnnotation DisplayName attribute for a given enum (for displaying enums values nicely to users)
/// </summary>
/// <param name="value">Enum value to get display for</param>
/// <returns>Pretty version of enum (if there is one)</returns>
/// <remarks>
/// Inspired by :
///     http://stackoverflow.com/questions/9328972/mvc-net-get-enum-display-name-in-view-without-having-to-refer-to-enum-type-in-vi
/// </remarks>
public static string DisplayFor(this Enum value) {
    Type enumType = value.GetType();
    var enumValue = Enum.GetName(enumType, value);
    MemberInfo member = enumType.GetMember(enumValue)[0];
    string outString = "";
    var attrs = member.GetCustomAttributes(typeof(DisplayAttribute), false);
    if (attrs.Any()) {
        var displayAttr = ((DisplayAttribute)attrs[0]);
        outString = displayAttr.Name;
        if (displayAttr.ResourceType != null) {
            outString = displayAttr.GetName();
        }
    } else {
        outString = value.ToString();
    }
    return outString;
}

@jrummell在VB.NET中为我们中的少数人提供的答案…

Module ModuleExtension
    <Extension()>
    Public Function DisplayName(ByVal value As System.Enum) As String
        Dim enumType As Type = value.GetType()
        Dim enumValue = System.Enum.GetName(enumType, value)
        Dim member As MemberInfo = enumType.GetMember(enumValue)(0)
        Dim attrs = member.GetCustomAttributes(GetType(DisplayAttribute), False)
        Dim outString = CType(attrs(0), DisplayAttribute).Name
        If (CType(attrs(0), DisplayAttribute).ResourceType IsNot Nothing) Then
            outString = CType(attrs(0), DisplayAttribute).GetName()
        End If
        Return outString
    End Function

End Module

对于任何可能提出这个问题的人来说,我发现这比其他任何事情都容易得多:https://www.codeproject.com/articles/776908/dealing-with-enum-in-mvc

只需在"Views\Shared"下创建一个文件夹"DisplayTemplate",并在新文件夹"DisplayTemplate"中创建一个空视图(名称为"Enum"),并将此代码复制到它"

@model Enum
@if (EnumHelper.IsValidForEnumHelper(ViewData.ModelMetadata))
{
    // Display Enum using same names (from [Display] attributes) as in editors
    string displayName = null;
    foreach (SelectListItem item in EnumHelper.GetSelectList(ViewData.ModelMetadata, (Enum)Model))
    {
        if (item.Selected)
        {
            displayName = item.Text ?? item.Value;
        }
    }
    // Handle the unexpected case that nothing is selected
    if (String.IsNullOrEmpty(displayName))
    {
        if (Model == null)
        {
            displayName = String.Empty;
        }
        else
        {
            displayName = Model.ToString();
        }
    }
    @Html.DisplayTextFor(model => displayName)
}
else
{
    // This Enum type is not supported.  Fall back to the text.
    @Html.DisplayTextFor(model => model)
}

下面是我编写的一个扩展方法。。。它有一个额外的逻辑来解析Enum名称并用大写字母分隔。您可以使用显示属性覆盖任何名称

public static TAttribute GetAttribute<TAttribute>(this ICustomAttributeProvider parameterInfo) where TAttribute : Attribute
{
    object[] attributes = parameterInfo.GetCustomAttributes(typeof(TAttribute), false);
    return attributes.Length > 0 ? (TAttribute)attributes[0] : null;
}
public static bool HasAttribute<TAttribute>(this ICustomAttributeProvider parameterInfo) where TAttribute : Attribute
{
    object[] attributes = parameterInfo.GetCustomAttributes(typeof(TAttribute), false);
    return attributes.Length > 0 ? true : false;
}
public static string ToFriendlyEnum(this Enum type)
{
    return type.GetType().HasAttribute<DescriptionAttribute>() ? type.GetType().GetAttribute<DescriptionAttribute>().Description : type.ToString().ToFriendlyEnum();
}
public static string ToFriendlyEnum(this string value)
{
    char[] chars = value.ToCharArray();
    string output = string.Empty;
    for (int i = 0; i < chars.Length; i++)
    {
        if (i <= 0 || chars[i - 1].ToString() != chars[i - 1].ToString().ToUpper() && chars[i].ToString() != chars[i].ToString().ToLower())
        {
            output += " ";
        }
        output += chars[i];
    }
    return output.Trim();
}

GetAttribute扩展方法可能有点过头了,但我在项目的其他地方使用了它们,所以当我编写Enum扩展时,它们得到了重用。您可以很容易地将它们组合回ToFriendlyEnum(此Enum类型)方法

建议的解决方案对我的MVC3不起作用:所以下面的助手很好。:

    public static string GetEnumDescription(this Enum value)
    {
        Type type = value.GetType();
        string name = Enum.GetName(type, value);
        if (name != null)
        {
            FieldInfo field = type.GetField(name);
            if (field != null)
            {
                string attr = field.GetCustomAttributesData()[0].NamedArguments[0].TypedValue.Value.ToString();
                if (attr == null)
                {
                    return name;
                }
                else
                {
                    return attr;
                }
            }
        }
        return null;
    }

最新更新