.NET 枚举:更上一层楼






4.53/5 (42投票s)
如何将对象与您的枚举值相关联。
引言
在本文中,我将进一步探讨枚举。 我不会介绍关于枚举的基本信息(您可以随时参考 MSDN 获取详细信息)。 我对枚举最大的不满是它只表示数值数据。 它可以灵活地表示不同的整数类型,但不能保存字符串。 枚举确实支持 ToString()
函数;但是,存在限制(我将在本文后面详细介绍)。 基本上,我希望能够使我的枚举元素与不仅仅是一个整数值相关联。 为了实现这一点,我将使用反射和属性,并尽量使我的示例尽可能简单。
使用 ToString() 和枚举
让我们创建一个简单的枚举...
public enum EmployeeType
{
RegularEmployee,
StoreManager,
ChainStoreManager,
DepartmentManager,
Supervisor
}
基于这个简单的普通枚举,我们可以获得以下信息: 使用 ToString()
的 String
表示形式。
EmployeeType employee = EmployeeType.ChainStoreManager;
Console.WriteLine(employee.ToString());
Console.WriteLine(EmployeeType.ChainStoreManager.ToString());
两行代码的输出相同
ChainStoreManager
ChainStoreManager
但是,如果我想得到带有空格的“连锁店经理”怎么办? 您不能创建包含空格的枚举类型,您的代码将无法编译。 这个问题有很多解决方案。
- 创建枚举和字符串之间的映射(使用数组或哈希表)。
- 使用枚举
ToString()
作为语言资源文件的键。 - 使用一点反射。
我将探索选项 3...
将属性与枚举一起使用
为了将字符串与枚举关联,我使用了属性。 我将从一个简单的示例开始,该示例会将我的枚举与一个字符串相关联。
public class EnumDescriptionAttribute : Attribute
{
private string m_strDescription;
public EnumDescriptionAttribute(string strPrinterName)
{
m_strDescription = strPrinterName;
}
public string Description
{
get { return m_strDescription; }
}
}
EnumDescriptionAttribute
是一个保存字符串的简单属性。 该属性具有一个单一属性来返回描述。 现在,我将尽量保持简单。 现在我已经有了我的描述属性,我将把它与每个枚举元素关联起来。
public enum EmployeeType
{
[EnumDescription("Regular Employee")]
RegularEmploye,
[EnumDescription("Store Manager")]
StoreManager,
[EnumDescription("Chain Store Manager")]
ChainStoreManager,
[EnumDescription("Department Manager")]
DepartmentManager,
[EnumDescription("On Floor Supervisor")]
Supervisor
}
从枚举中获取属性值
为了从枚举中获取属性值,我必须使用反射。 这是一个例子
// setup the enum
EmployeeType employee = EmployeeType.ChainStoreManager;
// get the field informaiton
FieldInfo fieldInfo = employee.GetType().GetField("ChainStoreManager");
// get the attributes for the enum field
object[] attribArray = fieldInfo.GetCustomAttributes(false);
// cast the one and only attribute to EnumDescriptionAttribute
EnumDescriptionAttribute attrib =
(EnumDescriptionAttribute)attribArray[0];
// write the description
console.WriteLine("Description: {0}", attrib.Description);
输出
Chain Store Manager
最重要的代码行是: FieldInfo fieldInfo = employee.GetType().GetField("ChainStoreManager");
。 请注意,我硬编码了枚举元素名称 *ChainStoreManager*,但如果您返回并查看 ToString()
函数,您可以看到我可以改用 ToString()
。
获取描述的泛型函数
请注意,我在枚举上使用了 ToString()
...
public static string GetEnumDescription(Enum enumObj)
{
FieldInfo fieldInfo =
enumObj.GetType().GetField(enumObj.ToString());
object[] attribArray = fieldInfo.GetCustomAttributes(false);
if (attribArray.Length == 0)
return String.Empty;
else
{
EnumDescriptionAttribute attrib =
attribArray[0] as EnumDescriptionAttribute;
return attrib.Description;
}
}
让我们将不仅仅是一个字符串与我们的枚举元素相关联
到目前为止,我们只将描述与我们的枚举元素相关联。 但是,完全可以将任何类型的数据与我们的枚举相关联。 为了说明这一点,我将创建一个新的枚举(类似于第一个)。
public enum ManagerType
{
StoreManager,
ChainManager,
Superivor
}
我还创建了一个新的属性类,ManagerAttribute
,它继承自 EnumDescription
,并提供两个附加信息(最低工资和最高工资)。
public class ManagerAttribute : EnumDescriptionAttribute
{
private int m_intMinSalary;
private int m_intMaxSalary;
public ManagerAttribute(string strDescription,
int intMinSalary,
int intMaxSalary) : base(strDescription)
{
m_intMinSalary = intMinSalary;
m_intMaxSalary = intMaxSalary;
}
public ManagerAttribute(string strDescription)
: base(strDescription)
{
}
public int MinSalary
{
get {return m_intMinSalary;}
set { m_intMinSalary = value; }
}
public int MaxSalary
{
get { return m_intMaxSalary;}
set { m_intMaxSalary = value; }
}
}
现在,我将把一个 ManagerAttribute
与每个枚举元素相关联。 请注意,我在我的 ManagerAttribute
中使用 set
属性,因此代码更具可读性
public enum ManagerType
{
[Manager("Store Manager", MinSalary=40000, MaxSalary=100000)]
StoreManager,
[Manager("Chain Manager", MinSalary=50000, MaxSalary=110000)]
ChainManager,
[Manager("Store Supervisor", MinSalary=30000, MaxSalary=50000)]
Superivor
}
下一步是改进我们的泛型函数,以允许我们获取任何类型的 EnumDescriptionAttribute
;使用泛型,这很容易做到!
public static T GetAttribute<T>(Enum enumObj) where T : EnumDescriptionAttribute
{
// get field informaiton for our enum element
FieldInfo fieldInfo = enumObj.GetType().GetField(enumObj.ToString());
// get all the attributes associated with our enum
object[] attribArray = fieldInfo.GetCustomAttributes(false);
if (attribArray.Length == 0)
return default(T);
else
{
// cast the attribute and return it
T attrib = (T)attribArray[0];
if (attrib != null)
return attrib;
else
return default(T);
}
}
辅助函数
到目前为止,我们有两个辅助函数,一个用于获取枚举的简单字符串描述,另一个用于获取从 EnumDescriptionAttribute
继承的任何属性的更通用的函数。 您可以将这些辅助函数添加到像 EnumHelper
这样的类中; 但是,在这个例子中,我决定简单地将它们添加到现有的 EnumDescriptionAttribute
中。
public class EnumDescriptionAttribute : Attribute
{
private string m_strDescription;
public EnumDescriptionAttribute(string strEnumDescription)
{
m_strDescription = strEnumDescription;
}
public string Description { get { return m_strDescription; } }
public static string GetEnumDescription(Enum enumObj)
{
FieldInfo fieldInfo = enumObj.GetType().GetField(enumObj.ToString());
object[] attribArray = fieldInfo.GetCustomAttributes(false);
if (attribArray.Length == 0)
return String.Empty;
else
{
EnumDescriptionAttribute attrib = attribArray[0]
as EnumDescriptionAttribute;
return attrib.Description;
}
}
public static T GetAttribute<T>(Enum enumObj)
where T : EnumDescriptionAttribute
{
FieldInfo fieldInfo = enumObj.GetType().GetField(enumObj.ToString());
object[] attribArray = fieldInfo.GetCustomAttributes(false);
if (attribArray.Length == 0)
return default(T);
else
{
T attrib = (T)attribArray[0];
if (attrib != null)
return attrib;
else
return default(T);
}
}
}
最后... 让我们把它们放在一起看看
要获取字符串描述,我们可以简单地这样做
string desc = EnumDescriptionAttribute.GetEnumDescription(EmployeeType.DepartmentManager);
要获取 ManagerAttribute
,我们可以这样做
ManagerAttribute manager =
EnumDescriptionAttribute.GetAttribute<ManagerAttribute>(
EmployeeType.DepartmentManager);
Console.WriteLine("Manager: {0}, Min Salary: {1}, Max Salary {2}",
attrib.Description,
manager.MinSalary,
manager.MaxSalary);
现在,您可以看到您可以使用属性将附加信息与枚举的元素相关联。
结论
好的,所以您可以看到通过简单地使用一些属性和反射,将附加信息与您的枚举元素相关联并不难。 但是,重要的是要注意,我不认为属性应该取代常见的业务对象。 我只是想表明一个枚举不必只表示一个整数值。 正如您在本文中读到的那样,您可以将枚举与字符串或任何其他类相关联。 使用属性的一个不错的优点是它易于实现,并且使代码可读。 您可以看到 ManagerType
枚举在实现 ManagerAttribute
后的可读性如何。 很容易知道每个枚举项包含什么。 我希望您喜欢阅读这篇文章,欢迎您提出任何意见或问题。