MVC.net получает отображаемое имя перечисления без необходимости ссылаться на тип перечисления в представлении - PullRequest
25 голосов
/ 17 февраля 2012

У меня есть следующий вспомогательный метод в классе ViewModelBase, который наследуется другими моделями представления:

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.wheteverEnum)

Нет typeof, нет T, нет необходимости добавлятьссылка на пространство имен Enums в представлении ...

Возможно?

Ответы [ 7 ]

54 голосов
/ 17 февраля 2012

Вы можете просто удалить параметр типа и сделать его методом расширения.

    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()
7 голосов
/ 17 февраля 2012

Не могли бы вы написать это как метод расширения?Что-то вроде ...

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();
5 голосов
/ 15 сентября 2013

Отличная работа @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 :
///     /5313062/mvc-net-poluchaet-otobrazhaemoe-imya-perechisleniya-bez-neobhodimosti-ssylatsya-tip-perechisleniya-predstavlenii
/// </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;
}
1 голос
/ 15 февраля 2017

для любого, кто может дойти до этого вопроса, я нашел это намного проще, чем что-либо еще: https://www.codeproject.com/articles/776908/dealing-with-enum-in-mvc

Просто создайте папку "DisplayTemplate" в "Views \ Shared" и создайте пустуюпросмотреть (назовите его «Enum») в новой папке «DisplayTemplate» и скопировать в него этот код «

@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)
}
1 голос
/ 17 июня 2014

Ответ @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
0 голосов
/ 21 октября 2013

Предлагаемые решения не работают для меня с MVC3: так что помощник ниже хорош.

0 голосов
/ 17 февраля 2012

Вот метод расширения, который я написал, чтобы сделать это ... в нем есть немного дополнительной логики для анализа имен 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)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...