从描述属性获取枚举
从描述属性获取枚举
我有一个通用的扩展方法,可以从枚举中获取Description
属性:
enum Animal { [Description("")] NotSet = 0, [Description("大熊猫")] GiantPanda = 1, [Description("小斑马")] 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(); // = "大熊猫"
现在,我正在尝试找出相反方向的等效函数,类似于...
Animal a = (Animal)Enum.GetValueFromDescription("大熊猫", typeof(Animal));
问题的原因是,如果在Web服务中使用该解决方案,将无法序列化Description属性。解决方法是使用DataContract特性和EnumMember特性来代替Description属性,并编写一个方法来获取枚举值的描述。
首先,在枚举定义中添加DataContract特性,并为每个枚举值添加EnumMember特性,用于指定其描述。然后,编写一个静态方法GetDescriptionFromEnumValue,该方法接受一个Enum类型的值作为参数,并通过反射获取该枚举值的EnumMemberAttribute特性,并返回其描述值。如果没有找到EnumMemberAttribute特性,则返回枚举值本身的字符串表示。
在使用GetDescriptionFromEnumValue方法之前,需要确保在代码中引入EnumMemberAttribute类所在的命名空间System.Runtime.Serialization。
这个解决方案非常适用于Web服务,因为它使用了与WCF(Windows Communication Foundation)兼容的EnumMember特性来提取枚举值的描述。
这个问题的解决方案是通过使用EnumMember特性和DataContract特性来代替Description属性,并编写一个方法来获取枚举值的描述。这个解决方案适用于Web服务,并且需要确保引入了System.Runtime.Serialization命名空间。
问题的出现原因是需要根据枚举类型的描述属性获取对应的枚举值,但是.NET Framework中没有直接提供这样的方法。为了解决这个问题,可以使用自定义的方法来实现。
解决方法是创建一个静态类`EnumEx`,其中包含一个泛型方法`GetValueFromDescription
可以通过以下方式调用该方法:
var panda = EnumEx.GetValueFromDescription("Giant Panda");
如果在方法签名中添加了`this`关键字,将其转换为扩展方法,则可以使用以下语法调用:
var x = "Giant Panda".GetValueFromDescription();
如果描述无效,可以使用以下方式判断:
var x = EnumEx.GetValueFromDescription("Dinosaur");
该调用会抛出异常,变量`x`不会包含任何值。
为了使代码正常工作,需要添加`using System.ComponentModel;`命名空间。
最后,还可以对比较进行不区分大小写的处理,可以使用`StringComparison.InvariantCultureIgnoreCase`参数来实现。
if (string.Equals(attribute.Description, description, StringComparison.InvariantCultureIgnoreCase)) return (T)field.GetValue(null);
总结起来,以上是解决从描述属性获取枚举值的问题的方法,通过自定义的方法和反射来实现这一功能,使得开发者能够更方便地根据描述属性获取对应的枚举值。
问题的出现原因是希望能够通过描述属性获取枚举值,但是在C#中没有直接的方法可以实现这一点。为了解决这个问题,代码中提供了两个静态方法,一个是根据枚举值获取描述属性的值,另一个是根据描述属性的值获取枚举值。
首先是获取描述属性的值的方法,它使用了反射来获取枚举值对应的字段,并通过字段的GetCustomAttributes方法获取描述属性的值。如果找到了描述属性,则返回其值,否则返回枚举值本身。
接下来是根据描述属性的值获取枚举值的方法,它首先判断泛型类型是否为枚举类型,如果不是则抛出ArgumentException异常。然后使用反射获取所有字段,并通过LINQ查询找到描述属性的值与目标值相匹配的字段。如果找到了匹配的字段,则返回其枚举值,否则返回默认值。
代码中还提到了一个性能问题,即value.ToString()方法的调用比较昂贵,建议不要重复调用。此外,还提到了一个改进方法,即在方法签名中添加"where T : Enum"的约束条件,这样就不需要在运行时再次检查泛型类型是否为枚举类型。
然而,C#并不支持直接在泛型约束中使用"where T : Enum"的语法。但是可以使用第三方库Fody.ExtraConstraints来实现相同的效果,该库可以在编译时将约束条件转换为有效的代码。
总之,通过这段代码可以实现通过描述属性获取枚举值的功能,并提供了一些优化和改进方法来提高性能和代码可读性。