How to get the Display Name Attribute of an Enum member via MVC razor code?
我的模型中有一个名为"promotion"的属性,它的类型是一个名为"userpromotion"的标志枚举。我的枚举成员的显示属性设置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | [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 } |
现在,我希望能够在我的视图中创建say-ul,以显示我的"提升"属性的选定值。这是我迄今为止所做的,但问题是如何在这里获取显示名称?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <ul> @foreach (int aPromotion in @Enum.GetValues(typeof(UserPromotion))) { var currentPromotion = (int)Model.JobSeeker.Promotion; if ((currentPromotion & aPromotion) == aPromotion) { <li> Here I don't know how to get the display attribute of"currentPromotion". </li> } } </ul> |
更新
第一个解决方案的重点是从枚举中获取显示名称。下面的代码应该是您的问题的确切解决方案。
可以将此帮助器类用于枚举:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Reflection; public static class EnumHelper<T> { public static IList<T> GetValues(Enum value) { var enumValues = new List<T>(); 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<string> GetNames(Enum value) { return value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public).Select(fi => fi.Name).ToList(); } public static IList<string> 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(); } } |
然后您可以在视图中使用它,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <ul> @foreach (var value in @EnumHelper<UserPromotion>.GetValues(UserPromotion.None)) { if (value == Model.JobSeeker.Promotion) { var description = EnumHelper<UserPromotion>.GetDisplayValue(value); <li> @Html.DisplayFor(e => description ) </li> } } </ul> |
希望它有帮助!:)
一行程序-流利的语法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public static class Extensions { /// <summary> /// A generic extension method that aids in reflecting /// and retrieving any attribute that is applied to an `Enum`. /// </summary> public static TAttribute GetAttribute<TAttribute>(this Enum enumValue) where TAttribute : Attribute { return enumValue.GetType() .GetMember(enumValue.ToString()) .First() .GetCustomAttribute<TAttribute>(); } } |
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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<DisplayAttribute>(); Console.WriteLine("Which season is it?"); Console.WriteLine (seasonDisplayName.Name); } } |
产量
Which season is it?
It's summer
基于Aydin的伟大答案,这里有一个不需要任何类型参数的扩展方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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<DisplayAttribute>() .GetName(); } } |
注意:应使用getname()而不是name属性。这样可以确保在使用ResourceType属性属性时返回本地化字符串。
例子
要使用它,只需引用视图中的枚举值。
1 2 3 4 5 | @{ UserPromotion promo = UserPromotion.SendJobOffersByMail; } Promotion: @promo.GetDisplayName() |
产量
晋升:通过邮件发送工作邀请
基于Aydin的回答,我建议使用一种"不那么重复"的实现(因为我们可以很容易地从
1 2 3 4 5 6 7 | public static string GetDisplayName(this Enum enumValue) { return enumValue.GetType().GetMember(enumValue.ToString()) .First() .GetCustomAttribute<DisplayAttribute>() .Name; } |
编辑(基于@vahagn nahapetyan的评论)
1 2 3 4 5 6 7 8 | public static string GetDisplayName(this Enum enumValue) { return enumValue.GetType()? .GetMember(enumValue.ToString())? .First()? .GetCustomAttribute<DisplayAttribute>()? .Name; } |
现在我们可以非常干净地使用它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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(); |
结果是
"The Dream"
如果您使用的是MVC 5.1或更高版本,那么有更简单、更清晰的方法:只需使用数据注释(来自
1 2 3 4 5 6 7 8 9 | public enum Color { [Display(Name ="Dark red")] DarkRed, [Display(Name ="Very dark red")] VeryDarkRed, [Display(Name ="Red or just black?")] ReallyDarkRed } |
在视图中,只需将其放入适当的HTML助手中:
1 | @Html.EnumDropDownListFor(model => model.Color) |
可以使用type.getmember方法,然后使用反射获取属性信息:
1 2 3 4 5 6 |
这里也有一些类似的帖子:
获取枚举值的属性
如何使MVC3显示为显示枚举的显示属性的值?
基于托德的伟大答案,这是建立在艾丁伟大答案的基础上的,这里有一个不需要任何类型参数的通用扩展方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /// <summary> /// Gets human-readable version of enum. /// </summary> /// <returns>DisplayAttribute.Name property of given enum.</returns> public static string GetDisplayName<T>(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<DisplayAttribute>(); string displayName = displayAttribute?.GetName(); return displayName ?? enumValue.ToString(); } |
我在我的项目中需要这样做,因为类似下面的代码(不是枚举的每个成员都有一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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 |
如果这是一个简单问题的复杂解决方案,请告诉我,但这是我使用的修复方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <ul> @foreach (int aPromotion in @Enum.GetValues(typeof(UserPromotion))) { var currentPromotion = (int)Model.JobSeeker.Promotion; if ((currentPromotion & aPromotion) == aPromotion) { <li> @Html.DisplayFor(e => currentPromotion) </li> } } </ul> |
要访问该属性,需要使用一些反射:
1 2 3 4 |
我建议将此方法包装在扩展方法中,或者在视图模型中执行此操作。
我很抱歉这么做,但我不能像现在那样使用其他任何答案,也没有时间在评论中加以讨论。
使用C 6语法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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<DisplayAttribute>(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<DisplayAttribute>()?.GetName(); static TAttribute GetEnumMemberAttribute<TAttribute>(this Enum value) where TAttribute : Attribute => value.GetType().GetEnumMemberAttribute<TAttribute>(value.ToString()); static TAttribute GetEnumMemberAttribute<TAttribute>(this Type enumType, string enumMemberName) where TAttribute : Attribute => enumType.GetMember(enumMemberName).Single().GetCustomAttribute<TAttribute>(); } |
在Aydin和Todd答案的基础上,这里还有一个扩展方法,它还允许您从资源文件中获取名称。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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<DisplayAttribute>(); } 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); } } |
并使用它
1 2 3 4 5 |
核心2.1,
1 2 3 4 5 6 7 | public static string GetDisplayName(Enum enumValue) { return enumValue.GetType()? .GetMember(enumValue.ToString())?[0]? .GetCustomAttribute<DisplayAttribute>()? .Name; } |
基于前面的答案,我创建了这个舒适的助手,以可读的方式支持所有DisplayAttribute属性:
16使用MVC5,您可以使用:
25然后,如果要创建下拉选择器,可以使用:
1 | @Html.EnumDropdownListFor(expression: model => model.PromotionSelector, optionLabel:"Select") |
我试着把它作为一个编辑来做,但被拒绝了,我不明白为什么。
如果您使用一个混合了自定义属性和普通项的枚举来调用它,那么上面将抛出一个异常,例如。
1 2 3 4 5 6 7 8 | public enum CommentType { All = 1, Rent = 2, Insurance = 3, [Display(Name="Service Charge")] ServiceCharge = 4 } |
所以我稍微修改了代码,以便在尝试访问自定义属性之前检查它们,如果没有找到,则使用名称。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Reflection; public static class EnumHelper<T> { public static IList<T> GetValues(Enum value) { var enumValues = new List<T>(); 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<string> GetNames(Enum value) { return value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public).Select(fi => fi.Name).ToList(); } public static IList<string> 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(); } } |
我想为依赖于区域性的getDisplayName枚举扩展做出贡献。希望这对像我一样在谷歌上搜索这个答案的人有用:
正如Aydin Adn和Todd提到的"Standart"方式:
1 2 3 4 5 6 7 8 9 | public static string GetDisplayName(this Enum enumValue) { return enumValue .GetType() .GetMember(enumValue.ToString()) .First() .GetCustomAttribute<DisplayAttribute>() .GetName(); } |
"文化依赖"方式:
1 2 3 4 5 6 7 8 9 10 11 12 | public static string GetDisplayName(this Enum enumValue, CultureInfo ci) { var displayAttr = enumValue .GetType() .GetMember(enumValue.ToString()) .First() .GetCustomAttribute<DisplayAttribute>(); var resMan = displayAttr.ResourceType?.GetProperty(@"ResourceManager", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null, null) as ResourceManager; return resMan?.GetString(displayAttr.Name, ci) ?? displayAttr.GetName(); } |