2013-06-02 81 views
4

所以我需要從我enum如何通過反射獲取枚舉值的所有描述?

這裏得到List<string>是我迄今所做的:

枚舉定義

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

助手類與方法做什麼,我需要:

​​

現在在我yield值的那一行,我得到了一個NullReferenceException。我錯過了什麼?語法看起來對我來說很好,但也許我忽略了一些東西?

編輯: 我在這裏使用.net Framework 4.0。

+0

由於這(顯然)是一個flags-enum,因此您的「收件人/傳遞」實際上不應該是valu e 3?像,不應該是'ContractorType.RECIPIENT |的組合ContractorType.DELIVER'?否則'(ContractorType.RECIPIENT | ContractorType.DELIVER)!= ContractorType.RECIPIENT_DELIVER'。也許你應該刪除'[Flags]'屬性。 –

回答

0

它認爲這可以解決您的問題。如果不執行,您可以返回null或發生異常。這取決於你需要什麼。

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

所以,你會使用這樣的:

DescriptionAttribute attribute = GetDescription(ContractorType.RECIPIENT); 

對不起,我沒有看過你的問題。下面是一些代碼,你可以用它來把所有的描述字符串:

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

你可以試試這個

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

是的,但是你的解決方案只適用於1種類型的自定義'enum',在樣例中是'ContractorType'我想要編寫方法來處理應用程序中所有可能的自定義枚舉器。所以這不是我所要求的 – harry180

+0

那麼你必須確定枚舉的類型,我認爲上面的答案之一使用它 –

2

你需要找到各領域的DescriptionAttribute,如果它存在,然後檢索例如Description屬性

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

如果你能有一個字段多描述,你可以這樣做:

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

這更類似於現有的方法。

+0

沒有'GetCustomAttributes()'0參數過載 – harry180

+0

@ harry180 - 這是一個擴展方法添加。 Net 4.5,所以如果你使用該版本的框架,你需要添加一個'使用System.Reflection'指令。或者,你可以使用帶'bool'參數的重載並傳遞false。我已經更新了使用該答案的答案。 – Lee

4

這是一個小的可重複使用的解決方案。這是一個抽象類,它將從類型T中提取類型爲K的所有屬性。

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

如果我們現在要只提取屬性DescriptionAttribute類型,我們可以使用下面的類。

class DescriptionAttributes<T> : AbstractAttributes<T, DescriptionAttribute> 
{ 
    public List<string> Descriptions { get; set; } 

    public DescriptionAttributes() 
    { 
     Descriptions = Attributes.Select(x => x.Description).ToList(); 
    } 
} 

該類將從類型T提取DescriptionAttribute類型的唯一的屬性。但要真正在你的情境中使用這個類,你只需要做以下事情。

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

這行代碼會寫出來,你作爲你的DescriptionAttribute類型的屬性參數的所有描述。如果需要提取一些其他屬性,只需創建一個從AbstractAttributes<T, K>類派生的新類,並使用適當的屬性關閉其類型K

1

我創建了這些擴展方法

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

使用

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

會返回一個​​與價值作爲鍵和說明值。如果你想只是一個列表,你可以改變.ToDictionary

.Select(o => (o as Enum).GetDescription()) 
.ToList() 
0

這是字典無法列出
不過是是我用

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

這個通用的靜態方法獲得的清單工作正常對於枚舉類型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); 
}