Come ottenere l’attributo Nome visualizzato di un membro Enum tramite il codice del razor MVC?

Ho una proprietà nel mio modello chiamata “Promozione” che il suo tipo è un flag enum chiamato “UserPromotion”. I membri del mio enum hanno attributi di visualizzazione impostati come segue:

[Flags] public enum UserPromotion { None = 0x0, [Display(Name = "Send Job Offers By Mail")] SendJobOffersByMail = 0x1, [Display(Name = "Send Job Offers By Sms")] SendJobOffersBySms = 0x2, [Display(Name = "Send Other Stuff By Sms")] SendPromotionalBySms = 0x4, [Display(Name = "Send Other Stuff By Mail")] SendPromotionalByMail = 0x8 } 

Ora voglio essere in grado di creare un ul a mio avviso per mostrare i valori selezionati della mia proprietà “Promozione”. Questo è quello che ho fatto finora ma il problema è che come posso ottenere qui i nomi dei display?

 
    @foreach (int aPromotion in @Enum.GetValues(typeof(UserPromotion))) { var currentPromotion = (int)Model.JobSeeker.Promotion; if ((currentPromotion & aPromotion) == aPromotion) {
  • Here I don't know how to get the display attribute of "currentPromotion".
  • } }

AGGIORNARE

La prima soluzione era focalizzata sull’ottenere i nomi visualizzati da enum. Il codice qui sotto dovrebbe essere la soluzione esatta per il tuo problema.

Puoi usare questa class di supporto per l’enumerazione:

 using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Reflection; public static class EnumHelper { public static IList GetValues(Enum value) { var enumValues = new List(); foreach (FieldInfo fi in value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public)) { enumValues.Add((T)Enum.Parse(value.GetType(), fi.Name, false)); } return enumValues; } public static T Parse(string value) { return (T)Enum.Parse(typeof(T), value, true); } public static IList GetNames(Enum value) { return value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public).Select(fi => fi.Name).ToList(); } public static IList GetDisplayValues(Enum value) { return GetNames(value).Select(obj => GetDisplayValue(Parse(obj))).ToList(); } private static string lookupResource(Type resourceManagerProvider, string resourceKey) { foreach (PropertyInfo staticProperty in resourceManagerProvider.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)) { if (staticProperty.PropertyType == typeof(System.Resources.ResourceManager)) { System.Resources.ResourceManager resourceManager = (System.Resources.ResourceManager)staticProperty.GetValue(null, null); return resourceManager.GetString(resourceKey); } } return resourceKey; // Fallback with the key name } public static string GetDisplayValue(T value) { var fieldInfo = value.GetType().GetField(value.ToString()); var descriptionAttributes = fieldInfo.GetCustomAttributes( typeof(DisplayAttribute), false) as DisplayAttribute[]; if (descriptionAttributes[0].ResourceType != null) return lookupResource(descriptionAttributes[0].ResourceType, descriptionAttributes[0].Name); if (descriptionAttributes == null) return string.Empty; return (descriptionAttributes.Length > 0) ? descriptionAttributes[0].Name : value.ToString(); } } 

E poi puoi usarlo nella tua vista come segue:

 
    @foreach (var value in @EnumHelper.GetValues(UserPromotion.None)) { if (value == Model.JobSeeker.Promotion) { var description = EnumHelper.GetDisplayValue(value);
  • @Html.DisplayFor(e => description )
  • } }

Spero che sia d’aiuto! 🙂

Una fodera: syntax fluente

 public static class Extensions { ///  /// A generic extension method that aids in reflecting /// and retrieving any attribute that is applied to an `Enum`. ///  public static TAttribute GetAttribute(this Enum enumValue) where TAttribute : Attribute { return enumValue.GetType() .GetMember(enumValue.ToString()) .First() .GetCustomAttribute(); } } 

Esempio

 public enum Season { [Display(Name = "It's autumn")] Autumn, [Display(Name = "It's winter")] Winter, [Display(Name = "It's spring")] Spring, [Display(Name = "It's summer")] Summer } public class Foo { public Season Season = Season.Summer; public void DisplayName() { var seasonDisplayName = Season.GetAttribute(); Console.WriteLine("Which season is it?"); Console.WriteLine (seasonDisplayName.Name); } } 

Produzione

In che stagione è?
È estate

Basandosi sulla grande risposta di Aydin , ecco un metodo di estensione che non richiede alcun parametro di tipo.

 using System; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Reflection; public static class EnumExtensions { public static string GetDisplayName(this Enum enumValue) { return enumValue.GetType() .GetMember(enumValue.ToString()) .First() .GetCustomAttribute() .GetName(); } } 

NOTA: è necessario utilizzare GetName () al posto della proprietà Name. Ciò garantisce che la stringa localizzata venga restituita se si utilizza la proprietà dell’attributo ResourceType.

Esempio

Per usarlo, basta fare riferimento al valore enum nella tua vista.

 @{ UserPromotion promo = UserPromotion.SendJobOffersByMail; } Promotion: @promo.GetDisplayName() 

Produzione

Promozione: invia offerte di lavoro per posta

Basandomi sulla risposta di Aydin suggerirei un’implementazione meno “duplicata” (perché potremmo facilmente ottenere il Type dal valore Enum stesso, invece di fornirlo come parametro 😉:

 public static string GetDisplayName(this Enum enumValue) { return enumValue.GetType().GetMember(enumValue.ToString()) .First() .GetCustomAttribute() .Name; } 

EDIT (basato sul commento di @Vahagn Nahapetyan)

 public static string GetDisplayName(this Enum enumValue) { return enumValue.GetType()? .GetMember(enumValue.ToString())? .First()? .GetCustomAttribute()? .Name; } 

Ora possiamo usarlo molto pulito in questo modo:

 public enum Season { [Display(Name = "The Autumn")] Autumn, [Display(Name = "The Weather")] Winter, [Display(Name = "The Tease")] Spring, [Display(Name = "The Dream")] Summer } Season.Summer.GetDisplayName(); 

Quale risulta in

“Il sogno”

Se stai utilizzando MVC 5.1 o superiore, c’è un modo più semplice e chiaro: basta usare l’annotazione dei dati (dallo spazio System.ComponentModel.DataAnnotations nomi System.ComponentModel.DataAnnotations ) come di seguito:

 public enum Color { [Display(Name = "Dark red")] DarkRed, [Display(Name = "Very dark red")] VeryDarkRed, [Display(Name = "Red or just black?")] ReallyDarkRed } 

E in vista, mettilo nel giusto helper html:

 @Html.EnumDropDownListFor(model => model.Color) 

È ansible utilizzare il metodo Type.GetMember , quindi ottenere le informazioni sull’attributo utilizzando reflection:

 // display attribute of "currentPromotion" var type = typeof(UserPromotion); var memberInfo = type.GetMember(currentPromotion.ToString()); var attributes = memberInfo[0].GetCustomAttributes(typeof(DisplayAttribute), false); var description = ((DisplayAttribute)attributes[0]).Name; 

C’erano alcuni post simili qui:

Ottenere attributi del valore di Enum

Come rendere MVC3 DisplayFor mostrare il valore di un attributo di visualizzazione di Enum?

 
    @foreach (int aPromotion in @Enum.GetValues(typeof(UserPromotion))) { var currentPromotion = (int)Model.JobSeeker.Promotion; if ((currentPromotion & aPromotion) == aPromotion) {
  • @Html.DisplayFor(e => currentPromotion)
  • } }

È necessario utilizzare un po ‘di riflessione per accedere a questo attributo:

 var type = typeof(UserPromotion); var member = type.GetMember(Model.JobSeeker.Promotion.ToString()); var attributes = member[0].GetCustomAttributes(typeof(DisplayAttribute), false); var name = ((DisplayAttribute)attributes[0]).Name; 

Raccomando di avvolgere questo metodo in un metodo di estensione o eseguirlo in un modello di vista.

Basandosi sulla grande risposta di Todd basata sulla grande risposta di Aydin , ecco un metodo di estensione generico che non richiede alcun parametro di tipo.

 ///  /// Gets human-readable version of enum. ///  /// DisplayAttribute.Name property of given enum. public static string GetDisplayName(this T enumValue) where T : IComparable, IFormattable, IConvertible { if (!typeof(T).IsEnum) throw new ArgumentException("Argument must be of type Enum"); DisplayAttribute displayAttribute = enumValue.GetType() .GetMember(enumValue.ToString()) .First() .GetCustomAttribute(); string displayName = displayAttribute?.GetName(); return displayName ?? enumValue.ToString(); } 

Avevo bisogno di questo per il mio progetto perché qualcosa come il codice qui sotto, dove non tutti i membri dell’enum hanno un DisplayAttribute , non funziona con la soluzione di Todd:

 public class MyClass { public enum MyEnum { [Display(Name="ONE")] One, // No DisplayAttribute Two } public void UseMyEnum() { MyEnum foo = MyEnum.One; MyEnum bar = MyEnum.Two; Console.WriteLine(foo.GetDisplayName()); Console.WriteLine(bar.GetDisplayName()); } } // Output: // // ONE // Two 

Se questa è una soluzione complicata a un problema semplice, faccelo sapere, ma questa era la soluzione che ho usato.

Sviluppando ulteriormente le risposte di Aydin e Todd, ecco un metodo di estensione che consente anche di ottenere il nome da un file di risorse

 using AppResources; using System; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Reflection; using System.Resources; public static class EnumExtensions { public static string GetDisplayName(this Enum enumValue) { var enumMember= enumValue.GetType() .GetMember(enumValue.ToString()); DisplayAttribute displayAttrib = null; if (enumMember.Any()) { displayAttrib = enumMember .First() .GetCustomAttribute(); } string name = null; Type resource = null; if (displayAttrib != null) { name = displayAttrib.Name; resource = displayAttrib.ResourceType; } return String.IsNullOrEmpty(name) ? enumValue.ToString() : resource == null ? name : new ResourceManager(resource).GetString(name); } } 

e usalo come

 public enum Season { [Display(ResourceType = typeof(Resource), Name = Season_Summer")] Summer } 

Mi dispiace farlo, ma non potrei usare nessuna delle altre risposte così com’è e non ho tempo di doppiarlo nei commenti.

Utilizza la syntax C # 6.

 static class EnumExtensions { /// returns the localized Name, if a [Display(Name="Localised Name")] attribute is applied to the enum member /// returns null if there isnt an attribute public static string DisplayNameOrEnumName(this Enum value) // => value.DisplayNameOrDefault() ?? value.ToString() { // More efficient form of ^ based on http://stackoverflow.com/a/17034624/11635 var enumType = value.GetType(); var enumMemberName = Enum.GetName(enumType, value); return enumType .GetEnumMemberAttribute(enumMemberName) ?.GetName() // Potentially localized ?? enumMemberName; // Or fall back to the enum name } /// returns the localized Name, if a [Display] attribute is applied to the enum member /// returns null if there is no attribute public static string DisplayNameOrDefault(this Enum value) => value.GetEnumMemberAttribute()?.GetName(); static TAttribute GetEnumMemberAttribute(this Enum value) where TAttribute : Attribute => value.GetType().GetEnumMemberAttribute(value.ToString()); static TAttribute GetEnumMemberAttribute(this Type enumType, string enumMemberName) where TAttribute : Attribute => enumType.GetMember(enumMemberName).Single().GetCustomAttribute(); } 

In base alle risposte precedenti ho creato questo comodo helper per supportare tutte le proprietà DisplayAttribute in modo leggibile:

 public static class EnumExtensions { public static DisplayAttributeValues GetDisplayAttributeValues(this Enum enumValue) { var displayAttribute = enumValue.GetType().GetMember(enumValue.ToString()).First().GetCustomAttribute(); return new DisplayAttributeValues(enumValue, displayAttribute); } public sealed class DisplayAttributeValues { private readonly Enum enumValue; private readonly DisplayAttribute displayAttribute; public DisplayAttributeValues(Enum enumValue, DisplayAttribute displayAttribute) { this.enumValue = enumValue; this.displayAttribute = displayAttribute; } public bool? AutoGenerateField => this.displayAttribute?.GetAutoGenerateField(); public bool? AutoGenerateFilter => this.displayAttribute?.GetAutoGenerateFilter(); public int? Order => this.displayAttribute?.GetOrder(); public string Description => this.displayAttribute != null ? this.displayAttribute.GetDescription() : string.Empty; public string GroupName => this.displayAttribute != null ? this.displayAttribute.GetGroupName() : string.Empty; public string Name => this.displayAttribute != null ? this.displayAttribute.GetName() : this.enumValue.ToString(); public string Prompt => this.displayAttribute != null ? this.displayAttribute.GetPrompt() : string.Empty; public string ShortName => this.displayAttribute != null ? this.displayAttribute.GetShortName() : this.enumValue.ToString(); } } 

Ho provato a farlo come una modifica ma è stato rifiutato; Non riesco a vedere perché.

Quanto sopra genererà un’eccezione se la chiami con un Enum che ha una combinazione di attributi personalizzati e elementi semplici, ad es

 public enum CommentType { All = 1, Rent = 2, Insurance = 3, [Display(Name="Service Charge")] ServiceCharge = 4 } 

Quindi ho modificato leggermente il codice per verificare la presenza di attributi personalizzati prima di tentare di accedervi e utilizzare il nome se non ne viene trovato nessuno.

 using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Reflection; public static class EnumHelper { public static IList GetValues(Enum value) { var enumValues = new List(); foreach (FieldInfo fi in value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public)) { enumValues.Add((T)Enum.Parse(value.GetType(), fi.Name, false)); } return enumValues; } public static T Parse(string value) { return (T)Enum.Parse(typeof(T), value, true); } public static IList GetNames(Enum value) { return value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public).Select(fi => fi.Name).ToList(); } public static IList GetDisplayValues(Enum value) { return GetNames(value).Select(obj => GetDisplayValue(Parse(obj))).ToList(); } private static string lookupResource(Type resourceManagerProvider, string resourceKey) { foreach (PropertyInfo staticProperty in resourceManagerProvider.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)) { if (staticProperty.PropertyType == typeof(System.Resources.ResourceManager)) { System.Resources.ResourceManager resourceManager = (System.Resources.ResourceManager)staticProperty.GetValue(null, null); return resourceManager.GetString(resourceKey); } } return resourceKey; // Fallback with the key name } public static string GetDisplayValue(T value) { var fieldInfo = value.GetType().GetField(value.ToString()); var descriptionAttributes = fieldInfo.GetCustomAttributes( typeof(DisplayAttribute), false) as DisplayAttribute[]; if (descriptionAttributes.Any() && descriptionAttributes[0].ResourceType != null) return lookupResource(descriptionAttributes[0].ResourceType, descriptionAttributes[0].Name); if (descriptionAttributes == null) return string.Empty; return (descriptionAttributes.Length > 0) ? descriptionAttributes[0].Name : value.ToString(); } } 

Con Core 2.1,

 public static string GetDisplayName(Enum enumValue) { return enumValue.GetType()? .GetMember(enumValue.ToString())?[0]? .GetCustomAttribute()? .Name; }