How to get all descriptions of enumeration values ​​with reflection?

So I need to get List<string> from my enum

Here is what I have done so far:

listing definition

  [Flags] public enum ContractorType { [Description("Recipient")] RECIPIENT = 1, [Description("Deliver")] DELIVER = 2, [Description("Recipient / Deliver")] RECIPIENT_DELIVER = 4 } 

HelperClass using the method to perform the necessary actions:

 public static class EnumUtils { public static IEnumerable<string> GetDescrptions(Type enumerator) { FieldInfo[] fi = enumerator.GetFields(); List<DescriptionAttribute> attributes = new List<DescriptionAttribute>(); foreach (var i in fi) { try { yield return attributes.Add(((DescriptionAttribute[])i.GetCustomAttributes( typeof(DescriptionAttribute), false))[0]); } catch { } } return new List<string>{"empty"}; } } 

Now in the line where the values ​​are yield , I got a NullReferenceException . Did I miss something? The syntax is right for me, but maybe I forgot something?

Edit: I am using the .NET Framework 4.0 here.

+4
source share
7 answers

Here is a small reusable solution. This is an abstract class that will extract all attributes of type K from type T.

 abstract class AbstractAttributes<T, K> { protected List<K> Attributes = new List<K>(); public AbstractAttributes() { foreach (var member in typeof(T).GetMembers()) { foreach (K attribute in member.GetCustomAttributes(typeof(K), true)) Attributes.Add(attribute); } } } 

If we want to extract only attributes of type DescriptionAttribute , we will use the following class.

 class DescriptionAttributes<T> : AbstractAttributes<T, DescriptionAttribute> { public List<string> Descriptions { get; set; } public DescriptionAttributes() { Descriptions = Attributes.Select(x => x.Description).ToList(); } } 

This class will retrieve only attributes of type DescriptionAttribute from type T But in order to actually use this class in your context, you just need to do the following.

 new DescriptionAttributes<ContractorType>().Descriptions.ForEach(x => Console.WriteLine(x)); 

This line of code will display all the descriptions that you used as parameters in your attributes of type DescriptionAttribute . If you need to extract some other attributes, just create a new class that comes from the AbstractAttributes<T, K> class and closes its type K with the corresponding attribute.

+4
source

You need to find a DescriptionAttribute in each field, if it exists, and then get the Description attribute, for example.

 return enumType.GetFields() .Select(f => (DescriptionAttribute)f.GetCustomAttribute(typeof(DescriptionAttribute))) .Where(a => a != null) .Select(a => a.Description) 

If you can have multiple descriptions in a field, you can do something like:

 FieldInfo[] fields = enumType.GetFields(); foreach(FieldInfo field in fields) { var descriptionAttributes = field.GetCustomAttributes(false).OfType<DescriptionAttribute>(); foreach(var descAttr in descriptionAttributes) { yield return descAttr.Description; } } 

which is more like your existing approach.

+2
source

I created these extension methods

 public static class EnumExtender { public static string GetDescription(this Enum enumValue) { string output = null; Type type = enumValue.GetType(); FieldInfo fi = type.GetField(enumValue.ToString()); var attrs = fi.GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[]; if (attrs.Length > 0) output = attrs[0].Description; return output; } public static IDictionary<T, string> GetEnumValuesWithDescription<T>(this Type type) where T : struct, IConvertible { if (!type.IsEnum) { throw new ArgumentException("T must be an enumerated type"); } return type.GetEnumValues() .OfType<T>() .ToDictionary( key => key, val => (val as Enum).GetDescription() ); } } 

Using

 var stuff = typeof(TestEnum).GetEnumValuesWithDescription<TestEnum>(); 

Will return the value Dictionary<TestEnum, string> with values ​​as keys and descriptions as values. If you only need a list, you can change .ToDictionary to

 .Select(o => (o as Enum).GetDescription()) .ToList() 
+1
source

He thinks this can solve your problem. If it is not implemented, you can return null or an exception. It depends on what you need.

 public DescriptionAttribute GetDescription(ContractorType contractorType) { MemberInfo memberInfo = typeof(ContractorType).GetMember(contractorType.ToString()) .FirstOrDefault(); if (memberInfo != null) { DescriptionAttribute attribute = (DescriptionAttribute) memberInfo.GetCustomAttributes(typeof(DescriptionAttribute), false) .FirstOrDefault(); return attribute; } //return null; //or throw new NotImplementedException("There is no description for this enum"); } 

So, you will use it as follows:

 DescriptionAttribute attribute = GetDescription(ContractorType.RECIPIENT); 

Sorry I did not read your question. Here is the code you can use to take all the lines of description:

  public IEnumerable<string> GetAllDescriptionInText() { List<string> descList = new List<string>(); foreach (DescriptionAttribute desc in Enum.GetValues(typeof(DescriptionAttribute))) { descList.Add(GetDescription(desc).Value); } return descList; } 
0
source

You can try this

 public string ContractorTypeDescription(Enum ContractorType) { FieldInfo fi = ContractorType.GetType().GetField(ContractorType.ToString()); var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); if (attributes.Length > 0) { return attributes[0].Description; } else { return ContractorType.ToString(); } } 
0
source

This is a dictionary without a list.
But this is what I use

 using System.ComponentModel; using System.Reflection; using MyExtensions; namespace MyExtensions { public static class Extension { public static string GetDescriptionName(this Enum value) { Type type = value.GetType(); string name = Enum.GetName(type, value); if (name == null) return null; else { FieldInfo field = type.GetField(name); if (field == null) return name; else { DescriptionAttribute attr = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; if (attr == null) return name; else return attr.Description; } } } } } namespace EnumDescription { class Program { public enum enumDateCond : byte { [Description("Empty")] Null = 0, [Description("Not Empty")] NotNull = 1, EQ = 2, LT = 3, LE = 4, GE = 14, GT = 15 }; static void Main(string[] args) { enumDateCond x = enumDateCond.Null; string description = x.GetDescriptionName(); foreach (enumDateCond enm in Enum.GetValues(typeof(enumDateCond))) { description = enm.GetDescriptionName(); Console.WriteLine(description); } Console.WriteLine("Dictionary"); Dictionary<enumDateCond, string> DLenumDateCond = EnumToDictionary<enumDateCond>(); foreach(enumDateCond key in DLenumDateCond.Keys) { Console.WriteLine(key.ToString() + " " + DLenumDateCond[key]); } } public static Dictionary<T, string> EnumToDictionary<T>() where T : struct { Type enumType = typeof(T); // Can't use generic type constraints on value types, // so have to do check like this if (enumType.BaseType != typeof(Enum)) throw new ArgumentException("T must be of type System.Enum"); Dictionary<T, string> enumDL = new Dictionary<T, string>(); foreach (T enm in Enum.GetValues(enumType)) { string name = Enum.GetName(enumType, enm); if (name != null) { FieldInfo field = enumType.GetField(name); if (field != null) { DescriptionAttribute attr = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; if (attr != null) name = attr.Description; } } enumDL.Add(enm, name); } return enumDL; } } } 
0
source

This general static method works great for getting a list of descriptions for each value of the enumeration type T:

 public static IEnumerable<string> GetDescriptions<T>() { var attributes = typeof(T).GetMembers() .SelectMany(member => member.GetCustomAttributes(typeof (DescriptionAttribute), true).Cast<DescriptionAttribute>()) .ToList(); return attributes.Select(x => x.Description); } 
0
source

Source: https://habr.com/ru/post/1484072/


All Articles