2010-12-06 3 views
173

Можно создать дубликат:
Finding an enum value by its Description AttributeGet Enum из описания атрибута

У меня есть универсальный метод расширения, который получает атрибут Description из Enum:

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 (это описание строки) ...он становится методом расширения, и вы можете использовать синтаксис, например: 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, так как это статический класс. Вы можете расширять только экземпляры типа. Имея это в виду, вам нужно будет создать статический метод для этого; должно работать в сочетании с существующим методом GetDescription:

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 ») Tiger}`, и вы вызываете `GetEnumFromString (« GiantPanda »)`, вы получите `GiantPanda` обратно, но я ожидаю` Тигр. Имейте функцию для чтения строки перечисления или ее описания. Смешивание обоих - плохой стиль API и может запутать клиентов. Или может быть его хорошим стилем, чтобы предотвратить ошибки пользователя :) – nawfal 2013-06-11 11:03:53

4

В случае, если быть довольно простым, это просто наоборот вашего предыдущего метода;

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; 
} 
Смежные вопросы