Получить перечисление из атрибута описания [дубликат]
Возможные Дубликаты:
поиск значения перечисления по его атрибуту описания
у меня есть универсальный метод расширения, который получает С 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));
6 ответов:
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");
вместо методов расширения, просто попробуйте несколько статических методов
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");
решение работает хорошо, за исключением случаев, когда у вас есть веб-служба.
вам нужно будет сделать следующее, Поскольку атрибут Description не сериализуем.
[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; }
должно быть довольно просто, это просто обратная сторона вашего предыдущего метода;
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)));
вы не можете продлить
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");
вам нужно перебрать все значения перечисления в Animal и вернуть значение, соответствующее описанию, которое вам нужно.
Comments