2016-03-21 87 views
1

有很多的例子中,你可以通過自定義獲取枚舉屬性喜歡這裏 Get Enum from Description attribute獲取枚舉通過自定義屬性(通用)

public static class EnumEx 
{ 
    public static T GetValueFromDescription<T>(string description) 
    { 
     var type = typeof(T); 
     if(!type.IsEnum) throw new InvalidOperationException(); 
     foreach(var field in type.GetFields()) 
     { 
      var attribute = Attribute.GetCustomAttribute(field, 
       typeof(DescriptionAttribute)) as DescriptionAttribute; 
      if(attribute != null) 
      { 
       if(attribute.Description == description) 
        return (T)field.GetValue(null); 
      } 
      else 
      { 
       if(field.Name == description) 
        return (T)field.GetValue(null); 
      } 
     } 
     throw new ArgumentException("Not found.", "description"); 
     // or return default(T); 
    } 
} 

但這裏的問題是,你有硬編碼的屬性類型,即typeof(DescriptionAttribute)) as DescriptionAttribute

如何將此示例轉換爲通用擴展,以便我不必硬編碼CustomAttributeType。

+1

作爲一種理念,你可以添加一個泛型參數的方法,但你應該知道的輸入參數的含義和用法能夠使用它進行搜索。例如,現在你可以使用這個標準if(attribute.Description == description)'但是當你傳遞一個泛型參數時呢? –

+2

那你怎麼翻譯這個:'attribute.Description'如果'attribute'不是'DescriptionAttribute'? – HimBromBeere

回答

5

這將爲您希望的值作爲字符串比較任意屬性的工作:

public static TEnum GetValueFromAttribute<TEnum, TAttribute> 
      (string text, Func<TAttribute, string> valueFunc) where TAttribute : Attribute 
{ 
    var type = typeof(TEnum); 
    if(!type.IsEnum) throw new InvalidOperationException(); 
    foreach(var field in type.GetFields()) 
    { 
     var attribute = Attribute.GetCustomAttribute(field, typeof(TAttribute)) as TAttribute; 
     if(attribute != null) 
     { 
      if(valueFunc.Invoke(attribute) == text) 
       return (TEnum)field.GetValue(null); 
     } 
     else 
     { 
      if(field.Name == text) 
       return (TEnum)field.GetValue(null); 
     } 
    } 
    throw new ArgumentException("Not found.", "text"); 
    // or return default(T); 
} 

,你會再打電話這樣的:

var value = GetValueFromAttribute<MyEnum, Description>("desc_text", a => a.Description); 
+0

你甚至可以直接調用你的func而不用'Invoke'來確保類型安全:'if(valueFunc(attribute)== text)'。但非常酷的答案。 – HimBromBeere

+0

@HimBromBeere這是一樣的(只是'Invoke'的一個快捷方式) –

0

您可以添加一個接口IDescription,即你的屬性實現:

public interface IDescription 
{ 
    string Description { get; } 
} 

public static class EnumEx 
{ 
    public static T GetValueFromDescription<T, TAttribute>(string description) where TAttribute : Attribute, IDescription 
    { 
     var type = typeof(T); 

     if (!type.IsEnum) throw new InvalidOperationException(); 

     foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Static)) 
     { 
      var attribute = (IDescription)Attribute.GetCustomAttribute(field, typeof(TAttribute)); 

      if (attribute != null) 
      { 
       if (attribute.Description == description) 
       { 
        return (T)field.GetValue(null); 
       } 
      } 
      else 
      { 
       if (field.Name == description) 
       { 
        return (T)field.GetValue(null); 
       } 
      } 
     } 

     throw new ArgumentException("Not found.", "description"); 
     // or return default(T); 
    } 
} 

或等同於完整的基礎類:

public abstract class BaseDescriptionAttribute : Attribute 
{ 
    public string Description { get; protected set; } 
} 

public static class EnumEx 
{ 
    public static T GetValueFromDescription<T, TAttribute>(string description) where TAttribute : BaseDescriptionAttribute 
    { 
     var type = typeof(T); 

     if (!type.IsEnum) throw new InvalidOperationException(); 

     foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Static)) 
     { 
      var attribute = (BaseDescriptionAttribute)Attribute.GetCustomAttribute(field, typeof(TAttribute)); 
0

添加一個新的通用型

public static T GetValueFromDescription<T, K>(string description) 

,並用它在GetCustomerAttribute

var attribute = Attribute.GetCustomAttribute(field, typeof(K));