2013-05-21 60 views
0

我想檢查Enum中是否存在任何枚舉中通過的代碼。問題是我的枚舉定義如下使用代碼屬性。在Enum屬性中搜索

public enum TestEnum 
    { 

     None, 

     [Code("FMNG")] 
     FunctionsManagement, 

     [Code("INST_MAST_MGT")] 
     MasterInstManagement 
} 

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] 
    public class CodeAttribute : Attribute 
    { 
     readonly string _code; 
     public string Code 
     { 
      get 
      { 
       return _code; 
      } 
     } 
     public CodeAttribute(string code) 
     { 
      _code = code; 
     } 
    } 

現在,我有可用的字符串(如「FMNG」),我想找尋回枚舉該枚舉與傳遞的字符串,這將是枚舉屬性存在。

我該如何檢查/得到使用或傳遞字符串的枚舉?我嘗試過使用Enum.IsDefined(typeof(ActivityEnum), "FMNG"),但它不適用於枚舉屬性。

+0

您可以用'Description'屬性,而不是'Code'的'enum'? – Habib

+0

實際上,代碼是預定義的,並且有50多個枚舉,因此我現在不能更改代碼屬性。 –

回答

1

這裏是一個通用的功能:

public static object ToEnum(string codeToFind, Type t) 
    { 
     foreach (var enumValue in Enum.GetValues(t)) 
     { 
      CodeAttribute[] codes = (CodeAttribute[])(enumValue.GetType().GetField(enumValue.ToString()). 
      GetCustomAttributes(typeof(CodeAttribute), false)); 

      if (codes.Length > 0 && codes[0].Code.Equals(codeToFind, StringComparison.InvariantCultureIgnoreCase) || 
       enumValue.ToString().Equals(codeToFind, StringComparison.InvariantCultureIgnoreCase)) 
       return enumValue; 
     } 

     return null; 
    } 

用法:var test = ToEnum("INST_MAST_MGT", typeof(TestEnum));

如果它發現所定義Code屬性或codeToFind參數等於枚舉的值的ToString上述函數將返回Enum值,你可以根據你的需要來調整它。

+3

如果你使你的方法是通用的,它可以有簽名'公共靜態T ToEnum (字符串codeToFind)其中T:struct'。請注意,如果枚舉定義了幾個具有相同數值的常量,則「Enum.GetValues」不是一個好的選擇。 –

+0

返回類型是Object能夠在找不到Code的情況下返回null值,這樣就更容易實現。 –

+0

如果你真的想要,你可以返回一個可爲空的'T',也被稱爲'T?'。或者你可以使用try-get模式:返回'bool'並使用'T'類型的'out'變量作爲結果。 –

0
public TestEnum GetEnumByAttributeName(string attributeName) 
{ 
    foreach (var item in Enum.GetNames(typeof(TestEnum))) 
    { 
     var memInfo = typeof(TestEnum).GetMember(item); 
     var attributes = memInfo[0].GetCustomAttributes(typeof(CodeAttribute), false); 
     if (attributes.Count()> 0 && ((CodeAttribute)attributes[0]).Code == attributeName) 
      return (TestEnum)Enum.Parse(typeof(TestEnum), item); 
    } 
    return TestEnum.None; 
} 
1

它也可能是一個想法,完全廢除的屬性,並創建一個靜態字典代碼:

static Dictionary<string, TestEnum> codeLookup = new Dictionary<string, TestEnum>() { 
                { "FMNG" , TestEnum.FunctionsManagement }, 
                { "INST_MAST_MGT", TestEnum.MasterInsManagement } }; 

然後就去做

bool isDefined = codeLookup.ContainsKey("FMNG"); 

這很可能是比每次使用反射來快速循環屬性更快,但這取決於您的需求

0

您可以將我們E本方法:

public static T GetEnumValueByAttributeString<T>(string code) where T : struct 
{ 
    if (!typeof(T).IsEnum) 
    throw new ArgumentException("T should be an enum"); 

    var matches = typeof(T).GetFields().Where(f => 
    ((CodeAttribute[])(f.GetCustomAttributes(typeof(CodeAttribute), false))).Any(c => c.Code == code) 
    ).ToList(); 

    if (matches.Count < 1) 
    throw new Exception("No match"); 
    if (matches.Count > 1) 
    throw new Exception("More than one match"); 

    return (T)(matches[0].GetValue(null)); 
} 

就像你看到的,它會檢查,如果你來用字符串是不明確的。使用這樣的:

var testEnum = GetEnumValueByAttributeString<TestEnum>("FMNG"); 

如果性能是一個問題,你可能要初始化,並保持所有的「翻譯」的Dictionary<string, T>,以便快速查找。

0

我發現下面的泛型方法:

public static T GetEnumValueFromDescription<T>(string description) 
     { 
      var type = typeof(T); 
      if (!type.IsEnum) 
       throw new ArgumentException(); 

      FieldInfo[] fields = type.GetFields(); 
      var field = fields.SelectMany(f => f.GetCustomAttributes(
           typeof(CodeAttribute), false), (
            f, a) => new { Field = f, Att = a }) 
          .Where(a => ((CodeAttribute)a.Att) 
           .Code == description).SingleOrDefault(); 
      return field == null ? default(T) : (T)field.Field.GetRawConstantValue(); 
     } 

來源:Get Enum from Description attribute