2012-02-17 12 views
23

tengo el siguiente método de ayuda en una clase ViewModelBase, que se hereda por otros modelos de vista:MVC.net get enumeración nombre para mostrar en la vista sin tener que referirse al tipo de enumeración en vista

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; 
     } 

entonces me llaman esto desde el punto de vista de esta manera:

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

la pregunta es - puedo trabajar este método así que no tengo que decir que el tipo de la enum? Básicamente me gustaría TODO esto para todos enum s:

@ Model.GetEnumDisplayName (Model.wheteverEnum)

Sin typeof, sin T, sin necesidad de añadir una referencia al espacio de nombres Enums en la vista ...

¿Posible?

Respuesta

54

Usted puede simplemente eliminar el parámetro de tipo y que sea un método de extensión.

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() 
+0

+1 muy agradable. se utiliza el código original y añade la implementación del código del método de extensión que incluye cómo llamarlo – Nope

+2

para c ompleteness sake, deberías agregar una comprobación de que hay cualquier 'DisplayAttributes' aplicado al valor enum y devolver' value.ToString() 'como valor predeterminado si no hay ninguno. De lo contrario, obtendrá un 'IndexOutOfRangeException' cuando llame a' ((DisplayAttribute) attrs [0]). Name' – flipchart

+0

Si alguien intenta llamar desde el controlador: DisplayName ((MyEnum) id); –

7

¿No podría escribir esto como método de extensión? Algo así como ...

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; 
    } 
} 

Uso:

@Model.WhateverEnum.ToDescription(); 
0

Aquí es un método de extensión que he escrito para hacer precisamente esto ... tiene un poco de lógica adicional en ella para analizar los nombres ENUM y dividir por letras mayúsculas. Puede anular cualquier nombre con el uso de la pantalla Atributo

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(); 
} 

Los métodos de extensión getAttribute podría estar ligeramente exagerado, pero yo los use en otra parte de mis proyectos, por lo que procuraron reutilizados cuando escribí mi extensión Enum. Puede combinarlos fácilmente de nuevo en el método ToFriendlyEnum (este tipo de Enum)

5

Buen trabajo @jrummell!

He añadido un pequeño pellizco por debajo del cual captura el escenario en el que una enumeración no tiene un Display atributo asociado (en la actualidad se produce una excepción)

/// <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; 
} 
0

Los sollutions sugeridas no trabajaban para mí con MVC3: por lo que el ayudante de abajo es bueno .:

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; 
    } 
1

la respuesta de @jrummell en VB.NET para los pocos de nosotros ...

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 
1

para cualquier persona que pudiera llegar a esta pregunta, he encontrado esta mucho más fácil que cualquier otra cosa: https://www.codeproject.com/articles/776908/dealing-with-enum-in-mvc

Basta con crear una carpeta "DisplayTemplate" bajo "Vistas \ Shared", y crear una Ver vacío (el nombre de "enumeración") en la nueva carpeta "DisplayTemplate", y copiar este código a ella"

@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) 
} 
Cuestiones relacionadas