2010-12-06 126 views
173

可能重复:
Finding an enum value by its Description Attribute得到Description属性枚举

我有后者从一个EnumDescription属性的通用扩展方法:

enum Animal 
{ 
    [Description("")] 
    NotSet = 0, 

    [Description("Giant Panda")] 
    GiantPanda = 1, 

    [Description("Lesser Spotted Anteater")] 
    LesserSpottedAnteater = 2 
} 

public static string GetDescription(this Enum value) 
{    
    FieldInfo field = value.GetType().GetField(value.ToString()); 

    DescriptionAttribute attribute 
      = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) 
       as DescriptionAttribute; 

    return attribute == null ? value.ToString() : attribute.Description; 
} 

所以我可以做...

string myAnimal = Animal.GiantPanda.GetDescription(); // = "Giant Panda" 

现在,我试图找出在其他方向上的同等功能,类似...

Animal a = (Animal)Enum.GetValueFromDescription("Giant Panda", typeof(Animal)); 

回答

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

用法:

var panda = EnumEx.GetValueFromDescription<Animal>("Giant Panda"); 
+36

如果在字符串前添加“this”关键字... public static T GetValueFromDescription (this string description)...它成为一种扩展方法,你可以使用如下语法:var x =“Giant Panda”.GetValueFromDescription (); – 2012-02-29 18:16:10

+0

我喜欢这种方法。适用于我,并且非常优雅。 – beaudetious 2012-09-25 17:58:22

0

您需要通过在动物中的所有枚举值迭代和返回值与您需要的描述相匹配。

+0

是的它得到了正确的枚举类型,我有点卡住了。 – fearofawhackplanet 2010-12-06 15:17:02

2

您不能扩展Enum,因为它是一个静态类。您只能扩展类型的实例。考虑到这一点,你将不得不自己创建一个静态方法来做到这一点;

public static class EnumHelper 
{ 
    public static T GetEnumFromString<T>(string value) 
    { 
     if (Enum.IsDefined(typeof(T), value)) 
     { 
      return (T)Enum.Parse(typeof(T), value, true); 
     } 
     else 
     { 
      string[] enumNames = Enum.GetNames(typeof(T)); 
      foreach (string enumName in enumNames) 
      { 
       object e = Enum.Parse(typeof(T), enumName); 
       if (value == GetDescription((Enum)e)) 
       { 
        return (T)e; 
       } 
      } 
     } 
     throw new ArgumentException("The value '" + value 
      + "' does not match a valid enum name or description."); 
    } 
} 

而且它的用法是这样的:

Animal giantPanda = EnumHelper.GetEnumFromString<Animal>("Giant Panda"); 
+2

这在逻辑上是错误的(虽然可以在明智的情况下工作)。例如,如果你的枚举类似`Animal {(“GiantPanda”)GiantPanda,(“GiantPanda”)Tiger}`,并且你调用`GetEnumFromString(“GiantPanda”)`,你会得到`GiantPanda`,老虎`回来。有一个读取枚举字符串或其描述的函数。将两者混合是一种糟糕的API风格,可能会让客户感到困惑。或者可能是防止用户错误的良好风格:) – nawfal 2013-06-11 11:03:53

4

要等到与您现有的方法GetDescription结合以下应该工作相当简单,它与你之前的方法相反;

public static int GetEnumFromDescription(string description, Type enumType) 
{ 
    foreach (var field in enumType.GetFields()) 
    { 
     DescriptionAttribute attribute 
      = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute))as DescriptionAttribute; 
     if(attribute == null) 
      continue; 
     if(attribute.Description == description) 
     { 
      return (int) field.GetValue(null); 
     } 
    } 
    return 0; 
} 

用法:

Console.WriteLine((Animal)GetEnumFromDescription("Giant Panda",typeof(Animal))); 
37

,而不是扩展方法,只是尝试了几个静态方法

public static class Utility 
{ 
    public static string GetDescriptionFromEnumValue(Enum value) 
    { 
     DescriptionAttribute attribute = value.GetType() 
      .GetField(value.ToString()) 
      .GetCustomAttributes(typeof (DescriptionAttribute), false) 
      .SingleOrDefault() as DescriptionAttribute; 
     return attribute == null ? value.ToString() : attribute.Description; 
    } 

    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(DescriptionAttribute), false), (
           f, a) => new { Field = f, Att = a }) 
         .Where(a => ((DescriptionAttribute)a.Att) 
          .Description == description).SingleOrDefault(); 
     return field == null ? default(T) : (T)field.Field.GetRawConstantValue(); 
    } 
} 

,并在这里使用

var result1 = Utility.GetDescriptionFromEnumValue(
    Animal.GiantPanda); 
var result2 = Utility.GetEnumValueFromDescription<Animal>(
    "Lesser Spotted Anteater"); 
12

解决方案的工作很好,除了如果你有一个网络服务。

您将需要执行以下操作,因为说明属性不可序列化。

[DataContract] 
public enum ControlSelectionType 
{ 
    [EnumMember(Value = "Not Applicable")] 
    NotApplicable = 1, 
    [EnumMember(Value = "Single Select Radio Buttons")] 
    SingleSelectRadioButtons = 2, 
    [EnumMember(Value = "Completely Different Display Text")] 
    SingleSelectDropDownList = 3, 
} 

public static string GetDescriptionFromEnumValue(Enum value) 
{ 
     EnumMemberAttribute attribute = value.GetType() 
      .GetField(value.ToString()) 
      .GetCustomAttributes(typeof(EnumMemberAttribute), false) 
      .SingleOrDefault() as EnumMemberAttribute; 
     return attribute == null ? value.ToString() : attribute.Value; 
}