获取Enum的值的属性

我想知道是否有可能获得枚举值的属性,而不是枚举本身? 例如,假设我有以下枚举:

using System.ComponentModel; // for DescriptionAttribute enum FunkyAttributesEnum { [Description("Name With Spaces1")] NameWithoutSpaces1, [Description("Name With Spaces2")] NameWithoutSpaces2 } 

我想要的是枚举types,产生2元组的枚举string值及其描述。

价值很简单:

 Array values = System.Enum.GetValues(typeof(FunkyAttributesEnum)); foreach (int value in values) Tuple.Value = Enum.GetName(typeof(FunkyAttributesEnum), value); 

但是如何获得description属性的值,来填充Tuple.Desc? 如果属性属于枚举本身,我可以考虑如何去做,但是我不知道如何从枚举值中得到它。

这应该做你需要的。

 var type = typeof(FunkyAttributesEnum); var memInfo = type.GetMember(FunkyAttributesEnum.NameWithoutSpaces1.ToString()); var attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); var description = ((DescriptionAttribute)attributes[0]).Description; 

这段代码应该给你一个很好的小扩展方法在任何枚举,让您检索一般属性。 我相信它和上面的lambda函数是不同的,因为它更简单,稍微简单 – 只需要传入genericstypes。

 public static class EnumHelper { /// <summary> /// Gets an attribute on an enum field value /// </summary> /// <typeparam name="T">The type of the attribute you want to retrieve</typeparam> /// <param name="enumVal">The enum value</param> /// <returns>The attribute of type T that exists on the enum value</returns> /// <example>string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description;</example> public static T GetAttributeOfType<T>(this Enum enumVal) where T:System.Attribute { var type = enumVal.GetType(); var memInfo = type.GetMember(enumVal.ToString()); var attributes = memInfo[0].GetCustomAttributes(typeof(T), false); return (attributes.Length > 0) ? (T)attributes[0] : null; } } 

这是一个使用lambda进行select的通用实现

  public static Expected GetAttributeValue<T, Expected>(this Enum enumeration, Func<T, Expected> expression) where T : Attribute { T attribute = enumeration .GetType() .GetMember(enumeration.ToString()) .Where(member => member.MemberType == MemberTypes.Field) .FirstOrDefault() .GetCustomAttributes(typeof(T), false) .Cast<T>() .SingleOrDefault(); if (attribute == null) return default(Expected); return expression(attribute); } 

像这样调用它:

 string description = targetLevel.GetAttributeValue<DescriptionAttribute, string>(x => x.Description); 

我已经在这里合并了一些答案来创build一个更加可扩展的解决scheme。 我提供它以防万一以后对其他人有帮助。 原帖在这里 。

 using System; using System.ComponentModel; public static class EnumExtensions { // This extension method is broken out so you can use a similar pattern with // other MetaData elements in the future. This is your base method for each. public static T GetAttribute<T>(this Enum value) where T : Attribute { var type = value.GetType(); var memberInfo = type.GetMember(value.ToString()); var attributes = memberInfo[0].GetCustomAttributes(typeof(T), false); return (T)attributes[0]; } // This method creates a specific call to the above method, requesting the // Description MetaData attribute. public static string ToName(this Enum value) { var attribute = value.GetAttribute<DescriptionAttribute>(); return attribute == null ? value.ToString() : attribute.Description; } } 

这个解决scheme在Enum上创build了一对扩展方法。 第一个允许您使用reflection来检索与您的值相关的任何属性。 第二个具体调用检索DescriptionAttribute并返回它的Description值。

作为一个例子,考虑使用来自System.ComponentModelDescriptionAttribute属性

 using System.ComponentModel; public enum Days { [Description("Sunday")] Sun, [Description("Monday")] Mon, [Description("Tuesday")] Tue, [Description("Wednesday")] Wed, [Description("Thursday")] Thu, [Description("Friday")] Fri, [Description("Saturday")] Sat } 

要使用上述扩展方法,现在只需调用以下内容:

 Console.WriteLine(Days.Mon.ToName()); 

要么

 var day = Days.Mon; Console.WriteLine(day.ToName()); 

除了AdamCrawford的回应之外 ,我还创build了一个更专门化的扩展方法来获取描述。

 public static string GetAttributeDescription(this Enum enumValue) { var attribute = enumValue.GetAttributeOfType<DescriptionAttribute>(); return attribute == null ? String.Empty : attribute.Description; } 

因此,为了得到描述,你可以使用原来的扩展方法

 string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description 

或者你可以简单地在这里调用扩展方法:

 string desc = myEnumVariable.GetAttributeDescription(); 

这应该有希望使你的代码更具可读性。

stream利的一个class轮…

在这里我使用了包含NameDescription属性的DisplayAttribute

 public static DisplayAttribute GetDisplayAttributesFrom(this Enum enumValue, Type enumType) { return enumType.GetMember(enumValue.ToString()) .First() .GetCustomAttribute<DisplayAttribute>(); } 

 public enum ModesOfTransport { [Display(Name = "Driving", Description = "Driving a car")] Land, [Display(Name = "Flying", Description = "Flying on a plane")] Air, [Display(Name = "Sea cruise", Description = "Cruising on a dinghy")] Sea } void Main() { ModesOfTransport TransportMode = ModesOfTransport.Sea; DisplayAttribute metadata = TransportMode.GetDisplayAttributesFrom(typeof(ModesOfTransport)); Console.WriteLine("Name: {0} \nDescription: {1}", metadata.Name, metadata.Description); } 

产量

 Name: Sea cruise Description: Cruising on a dinghy 

这是从Display属性获取信息的代码。 它使用一个通用的方法来检索属性。 如果找不到该属性,它会将枚举值转换为一个string,并将pascal / camel大小写转换为标题大小写( 此处获得的代码)

 public static class EnumHelper { // Get the Name value of the Display attribute if the // enum has one, otherwise use the value converted to title case. public static string GetDisplayName<TEnum>(this TEnum value) where TEnum : struct, IConvertible { var attr = value.GetAttributeOfType<TEnum, DisplayAttribute>(); return attr == null ? value.ToString().ToSpacedTitleCase() : attr.Name; } // Get the ShortName value of the Display attribute if the // enum has one, otherwise use the value converted to title case. public static string GetDisplayShortName<TEnum>(this TEnum value) where TEnum : struct, IConvertible { var attr = value.GetAttributeOfType<TEnum, DisplayAttribute>(); return attr == null ? value.ToString().ToSpacedTitleCase() : attr.ShortName; } /// <summary> /// Gets an attribute on an enum field value /// </summary> /// <typeparam name="TEnum">The enum type</typeparam> /// <typeparam name="T">The type of the attribute you want to retrieve</typeparam> /// <param name="value">The enum value</param> /// <returns>The attribute of type T that exists on the enum value</returns> private static T GetAttributeOfType<TEnum, T>(this TEnum value) where TEnum : struct, IConvertible where T : Attribute { return value.GetType() .GetMember(value.ToString()) .First() .GetCustomAttributes(false) .OfType<T>() .LastOrDefault(); } } 

这是用于转换为标题大小写的string的扩展方法:

  /// <summary> /// Converts camel case or pascal case to separate words with title case /// </summary> /// <param name="s"></param> /// <returns></returns> public static string ToSpacedTitleCase(this string s) { //https://stackoverflow.com/a/155486/150342 CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture; TextInfo textInfo = cultureInfo.TextInfo; return textInfo .ToTitleCase(Regex.Replace(s, "([az](?=[A-Z0-9])|[AZ](?=[AZ][az]))", "$1 ")); } 

从枚举中获取字典。

 public static IDictionary<string, int> ToDictionary(this Type enumType) { return Enum.GetValues(enumType) .Cast<object>() .ToDictionary(v => ((Enum)v).ToEnumDescription(), k => (int)k); } 

现在称之为…

 var dic = typeof(ActivityType).ToDictionary(); 

EnumDecription外部方法

 public static string ToEnumDescription(this Enum en) //ext method { Type type = en.GetType(); MemberInfo[] memInfo = type.GetMember(en.ToString()); if (memInfo != null && memInfo.Length > 0) { object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); if (attrs != null && attrs.Length > 0) return ((DescriptionAttribute)attrs[0]).Description; } return en.ToString(); } public enum ActivityType { [Description("Drip Plan Email")] DripPlanEmail = 1, [Description("Modification")] Modification = 2, [Description("View")] View = 3, [Description("E-Alert Sent")] EAlertSent = 4, [Description("E-Alert View")] EAlertView = 5 } 

我实现了这个扩展方法来获取来自枚举值的描述​​。 它适用于所有types的枚举。

 public static class EnumExtension { public static string ToDescription(this System.Enum value) { FieldInfo fi = value.GetType().GetField(value.ToString()); var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); return attributes.Length > 0 ? attributes[0].Description : value.ToString(); } } 

这里是AdamCrawford的答案的.NET Core版本,使用System.Reflection.TypeExtensions ;

 public static class EnumHelper { /// <summary> /// Gets an attribute on an enum field value /// </summary> /// <typeparam name="T">The type of the attribute you want to retrieve</typeparam> /// <param name="enumVal">The enum value</param> /// <returns>The attribute of type T that exists on the enum value</returns> /// <example>string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description;</example> public static T GetAttributeOfType<T>(this Enum enumVal) where T : System.Attribute { var type = enumVal.GetType(); var memInfo = type.GetMember(enumVal.ToString()); IEnumerable<Attribute> attributes = memInfo[0].GetCustomAttributes(typeof(T), false); return (T)attributes?.ToArray()[0]; } } 

利用一些较新的C#语言function,可以减less行数:

 public static TAttribute GetEnumAttribute<TAttribute>(this Enum enumVal) where TAttribute : Attribute { var memberInfo = enumVal.GetType().GetMember(enumVal.ToString()); return memberInfo[0].GetCustomAttributes(typeof(TAttribute), false).OfType<TAttribute>().FirstOrDefault(); } public static string GetEnumDescription(this Enum enumValue) => enumValue.GetEnumAttribute<DescriptionAttribute>()?.Description ?? enumValue.ToString(); 

此扩展方法将使用其XmlEnumAttribute获取枚举值的string表示forms。 如果不存在XmlEnumAttribute,则回退到enum.ToString()。

 public static string ToStringUsingXmlEnumAttribute<T>(this T enumValue) where T: struct, IConvertible { if (!typeof(T).IsEnum) { throw new ArgumentException("T must be an enumerated type"); } string name; var type = typeof(T); var memInfo = type.GetMember(enumValue.ToString()); if (memInfo.Length == 1) { var attributes = memInfo[0].GetCustomAttributes(typeof(System.Xml.Serialization.XmlEnumAttribute), false); if (attributes.Length == 1) { name = ((System.Xml.Serialization.XmlEnumAttribute)attributes[0]).Name; } else { name = enumValue.ToString(); } } else { name = enumValue.ToString(); } return name; } 

如果你想要完整的名单,你可以做类似的事情

 typeof (PharmacyConfigurationKeys).GetFields() .Where(x => x.GetCustomAttributes(false).Any(y => typeof(DescriptionAttribute) == y.GetType())) .Select(x => ((DescriptionAttribute)x.GetCustomAttributes(false)[0]).Description); 

我这个答案设置一个combobox从枚举属性是伟大的。

然后我需要编写相反的代码,以便我可以从框中select并返回正确types的枚举。

我还修改了代码来处理缺less属性的情况

对于下一个人的好处,这是我的最终解决scheme

 public static class Program { static void Main(string[] args) { // display the description attribute from the enum foreach (Colour type in (Colour[])Enum.GetValues(typeof(Colour))) { Console.WriteLine(EnumExtensions.ToName(type)); } // Get the array from the description string xStr = "Yellow"; Colour thisColour = EnumExtensions.FromName<Colour>(xStr); Console.ReadLine(); } public enum Colour { [Description("Colour Red")] Red = 0, [Description("Colour Green")] Green = 1, [Description("Colour Blue")] Blue = 2, Yellow = 3 } } public static class EnumExtensions { // This extension method is broken out so you can use a similar pattern with // other MetaData elements in the future. This is your base method for each. public static T GetAttribute<T>(this Enum value) where T : Attribute { var type = value.GetType(); var memberInfo = type.GetMember(value.ToString()); var attributes = memberInfo[0].GetCustomAttributes(typeof(T), false); // check if no attributes have been specified. if (((Array)attributes).Length > 0) { return (T)attributes[0]; } else { return null; } } // This method creates a specific call to the above method, requesting the // Description MetaData attribute. public static string ToName(this Enum value) { var attribute = value.GetAttribute<DescriptionAttribute>(); return attribute == null ? value.ToString() : attribute.Description; } /// <summary> /// Find the enum from the description attribute. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="desc"></param> /// <returns></returns> public static T FromName<T>(this string desc) where T : struct { string attr; Boolean found = false; T result = (T)Enum.GetValues(typeof(T)).GetValue(0); foreach (object enumVal in Enum.GetValues(typeof(T))) { attr = ((Enum)enumVal).ToName(); if (attr == desc) { result = (T)enumVal; found = true; break; } } if (!found) { throw new Exception(); } return result; } } 

}

为Net Framework和NetCore添加我的解决scheme。

我用这个为我的networking框架实现:

 public static class EnumerationExtension { public static string Description( this Enum value ) { // get attributes var field = value.GetType().GetField( value.ToString() ); var attributes = field.GetCustomAttributes( typeof( DescriptionAttribute ), false ); // return description return attributes.Any() ? ( (DescriptionAttribute)attributes.ElementAt( 0 ) ).Description : "Description Not Found"; } } 

这对NetCore不起作用,所以我修改它来执行此操作:

 public static class EnumerationExtension { public static string Description( this Enum value ) { // get attributes var field = value.GetType().GetField( value.ToString() ); var attributes = field.GetCustomAttributes( false ); // Description is in a hidden Attribute class called DisplayAttribute // Not to be confused with DisplayNameAttribute dynamic displayAttribute = null; if (attributes.Any()) { displayAttribute = attributes.ElementAt( 0 ); } // return description return displayAttribute?.Description ?? "Description Not Found"; } } 

枚举示例:

 public enum ExportTypes { [Display( Name = "csv", Description = "text/csv" )] CSV = 0 } 

添加了静态的示例用法:

 var myDescription = myEnum.Description(); 

或者,您可以执行以下操作:

 Dictionary<FunkyAttributesEnum, string> description = new Dictionary<FunkyAttributesEnum, string>() { { FunkyAttributesEnum.NameWithoutSpaces1, "Name With Spaces1" }, { FunkyAttributesEnum.NameWithoutSpaces2, "Name With Spaces2" }, }; 

并得到以下描述:

 string s = description[FunkyAttributesEnum.NameWithoutSpaces1]; 

在我看来,这是一个更有效的方式来完成你想要完成的任务,因为不需要反思。

伙计们,如果有帮助我会与你分享我的解决scheme:自定义属性的定义:

  [AttributeUsage(AttributeTargets.Field,AllowMultiple = false)] public class EnumDisplayName : Attribute { public string Name { get; private set; } public EnumDisplayName(string name) { Name = name; } } 

现在因为我需要它在HtmlHelper扩展的HtmlHelper定义里面:

 public static class EnumHelper { public static string EnumDisplayName(this HtmlHelper helper,EPriceType priceType) { //Get every fields from enum var fields = priceType.GetType().GetFields(); //Foreach field skipping 1`st fieldw which keeps currently sellected value for (int i = 0; i < fields.Length;i++ ) { //find field with same int value if ((int)fields[i].GetValue(priceType) == (int)priceType) { //get attributes of found field var attributes = fields[i].GetCustomAttributes(false); if (attributes.Length > 0) { //return name of found attribute var retAttr = (EnumDisplayName)attributes[0]; return retAttr.Name; } } } //throw Error if not found throw new Exception("Błąd podczas ustalania atrybutów dla typu ceny allegro"); } } 

希望它有帮助

你也可以定义一个枚举值,比如Name_Without_Spaces ,当你想要一个描述时,使用Name_Without_Spaces.ToString().Replace('_', ' ')用空格replace下划线。