枚举描述字典的实现与应用

在编程中,枚举(Enum)是一种常用的数据类型,它允许为一组相关的常量定义一个名称。枚举的名称通常简洁明了,但有时对于最终用户来说,这些名称可能不够描述性。因此,希望为枚举字段关联更长、更易于理解的描述,通常用于用户界面(UI)。例如,一个下拉框(ComboBox)的值可能来自枚举字段,而其文本可能来自该字段的描述。

为了实现这一目标,可以使用描述性属性(Description Attribute)来装饰枚举字段,以提供更详细的描述。然而,获取这些属性提供的描述需要使用反射(Reflection),这是应该尽量避免的操作。本文介绍的类允许一次性创建枚举类型的描述字典,以便在需要时随时使用。

使用代码

这个类继承自Dictionary,并且需要一个构造函数来初始化字典。为了使这个字典在所有方面都是只读的,并且字典中每个枚举成员的描述也是只读的,需要实现IDictionary接口,而不是仅仅继承Dictionary

以下是类的定义和实现:

public class EnumDescriptionDictionary : Dictionary where TEnum : struct, IComparable, IConvertible, IFormattable { public EnumDescriptionDictionary() { if (!typeof(TEnum).IsEnum) { throw new NotSupportedException("Generic parameter T must be of type Enum."); } var fields = typeof(TEnum).GetFields(BindingFlags.Public | BindingFlags.Static); foreach (var field in fields) { var descAtt = field.GetCustomAttribute(); if (descAtt != null) { var desc = descAtt.Description; if (!string.IsNullOrEmpty(desc)) { Add((TEnum)Enum.Parse(typeof(TEnum), field.Name), desc); continue; } } Add((TEnum)Enum.Parse(typeof(TEnum), field.Name), field.Name); } } public new void Remove(TEnum key) { throw new InvalidOperationException(string.Format("Items may not be removed from this dictionary as type '{0}' has not changed.", typeof(TEnum).Name)); } }

这个类首先检查泛型参数T是否为枚举类型。如果不是,它将抛出一个NotSupportedException异常。然后,它使用BindingFlags来获取枚举类型的所有公共静态字段,并遍历这些字段。对于每个字段,它尝试获取描述性属性(DescriptionAttribute)。如果找到了,并且属性的描述不为空,则将该描述添加到字典中。如果没有找到描述性属性,或者属性的描述为空,则使用字段的名称作为描述。

使用示例

以下是一个测试枚举和使用EnumDescriptionDictionary的示例程序:

internal enum TestEnum { [Description("Not Operational")] Nop, Installation, [Description("System Set-up")] SystemSetup, [Description("Import / Export")] ImportExport, Configuration, [Description("Help and Documentation")] Help, Uninstall } class Program { static void Main(string[] args) { var dict = new EnumDescriptionDictionary(); Console.WriteLine(); Console.WriteLine("Value: {0}\tDesc: '{1}'", TestEnum.Nop, dict[TestEnum.Nop]); Console.WriteLine("Value: {0}\tDesc: '{1}'", TestEnum.Configuration, dict[TestEnum.Configuration]); Console.WriteLine(); Console.WriteLine("Press Enter to exit."); Console.ReadLine(); } }

这个程序将输出以下内容:

Value: Nop Desc: 'Not Operational' Value: Configuration Desc: 'Configuration'

.NET没有提供原生的约束来指定泛型参数必须是枚举类型。但是,可以使用Jon Skeet的unconstrained-melody库来实现这一点。这个库提供了许多枚举实用工具,这些工具可以替代上面所做的工作。

The JIT compiler needs a definition of a value type that describes its layout when it gets boxed. Most of them are baked into mscorlib, like System.Int32. The enum keyword lets you create a new value type. The compiler must thus provide a definition for it in the metadata. Which is what you are looking at. You'll see static fields for each enumeration member, used by ToString(). And one instance field name value__ that stores the enumeration value. Key point is that this only exists in the boxed version of an enum value.
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485