带有描述的枚举字符串

我目前正在根据这个建议实现字符串和枚举的关联。 就是这样,我有一个与每个枚举元素相关联的Description属性。 在该页面上还有一个函数,它根据给定的枚举返回描述的字符串。 我现在要实现的是反向函数,也就是说,给定一个输入字符串查找带有相应描述的枚举(如果存在),否则返回null。

我试过(T) Enum.Parse(typeof(T), "teststring")但是它抛出exception。

你必须编写自己的反向方法。 库存Parse()方法显然不了解您的描述属性。

像这样的东西应该工作:

 public static T GetEnumValueFromDescription(string description) { MemberInfo[] fis = typeof(T).GetFields(); foreach (var fi in fis) { DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); if (attributes != null && attributes.Length > 0 && attributes[0].Description == description) return (T)Enum.Parse(typeof(T), fi.Name); } throw new Exception("Not found"); } 

如果没有找到枚举值,你会想要找到一个更好的事情而不是抛出exception。 🙂

 static string GetEnumDescription(T value) { FieldInfo fi = value.GetType().GetField(value.ToString()); DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes( typeof(DescriptionAttribute), false ); if (attributes != null && attributes.Length > 0) { return attributes[0].Description; } else { return value.ToString(); } } static T ParseDescriptionToEnum(string description) { Array array = Enum.GetValues(typeof(T)); var list = new List(array.Length); for(int i = 0; i < array.Length; i++) { list.Add((T)array.GetValue(i)); } var dict = list.Select(v => new { Value = v, Description = GetEnumDescription(v) } ) .ToDictionary(x => x.Description, x => x.Value); return dict[description]; } 

我没有尝试过错误检查。 请注意,不需要在每次调用方法时创建字典,但我太懒了,无法修复它。

用法:

 enum SomeEnum { [Description("First Value")] FirstValue, SecondValue } SomeEnum value = ParseDescriptionToEnum("First Value"); 

通过的测试:

 [Fact] public void Can_parse_a_value_with_a_description_to_an_enum() { string description = "First Value"; SomeEnum value = ParseDescriptionToEnum(description); Assert.Equal(SomeEnum.FirstValue, value); } [Fact] public void Can_parse_a_value_without_a_description_to_an_enum() { string description = "SecondValue"; SomeEnum value = ParseDescriptionToEnum(description); Assert.Equal(SomeEnum.SecondValue, value); } 

我会赞同安娜的回答,但我没有这样做的声誉。 部分基于她的答案,这是我提出的双向解决方案。 向ParseEnum方法提供defaultValue可以涵盖相同Enum根据其用法可能具有不同默认值的情况。

  public static string GetDescription(this object enumerationValue) where T : struct { // throw an exception if enumerationValue is not an Enum Type type = enumerationValue.GetType(); if (!type.IsEnum) { throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue"); } //Tries to find a DescriptionAttribute for a potential friendly name for the enum MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString()); if (memberInfo != null && memberInfo.Length > 0) { DescriptionAttribute[] attributes = (DescriptionAttribute[])memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false); if (attributes != null && attributes.Length > 0) { //Pull out the description value return attributes[0].Description; } } //In case we have no description attribute, we'll just return the ToString of the enum return enumerationValue.ToString(); } public static T ParseEnum(this string stringValue, T defaultValue) { // throw an exception if T is not an Enum Type type = typeof(T); if (!type.IsEnum) { throw new ArgumentException("T must be of Enum type", "T"); } //Tries to find a DescriptionAttribute for a potential friendly name for the enum MemberInfo[] fields = type.GetFields(); foreach (var field in fields) { DescriptionAttribute[] attributes = (DescriptionAttribute[])field.GetCustomAttributes(typeof(DescriptionAttribute), false); if (attributes != null && attributes.Length > 0 && attributes[0].Description == stringValue) { return (T)Enum.Parse(typeof(T), field.Name); } } //In case we couldn't find a matching description attribute, we'll just return the defaultValue that we provided return defaultValue; } 

您也可以使用Humanizer 。 要获得您所写的描述:

 EAssemblyUnit.eUCAL1.Humanize(); 

并从描述中获取枚举,这是你想要的,你可以写:

 "UCAL1".DehumanizeTo(); 

免责声明:我是Humanizer的创造者。

对相关问题的答案显示了如何检索给定类型的属性。 您可以使用类似的方法将给定字符串与Enum的描述属性进行比较。