带有描述的枚举字符串
我目前正在根据这个建议实现字符串和枚举的关联。 就是这样,我有一个与每个枚举元素相关联的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
的描述属性进行比较。