现在的位置: 首页 > 综合 > 正文

枚举

2013年12月06日 ⁄ 综合 ⁄ 共 5942字 ⁄ 字号 评论关闭
 导言

     
在这篇文章里我将对.NET中的枚举做进一步探索,本文不会含盖枚举的基本概念、语法或者使用方法(这些你可以通过MSDN得到详细的信息),最大的限制
是枚举只能使用 Integer 数据类型。枚举提供了 ToString()
方法的支持,但却有限制(我会在文章后面详细论述)。主要地,我希望能够把我所列举的枚举元素不仅仅关联到整数数据,我将通过反射
(Reflection)和属性(Attributes)跟使用尽量简单的例子来说明如何达到这一目标。
在 Enum 中使用 ToString()

我们先来创建一个简单的枚举。。。

public enum EmployeeType
{
    RegularEmployee,
    StoreManager,
    ChainStoreManager,
    DepartmentManager,
    Supervisor
}
我们可以通过 ToString() 方法简单地获取到下列信息

EmployeeType employee = EmployeeType.ChainStoreManager;
Console.WriteLine(employee.ToString());
Console.WriteLine(EmployeeType.ChainStoreManager.ToString());

/**//*
输出结果:

ChainStoreManager
ChainStoreManager
*/
但我们如何才能获取到的结果类似“Chain Store Manager”包括空格呢?我们不能去创建一个包含空格的枚举成员,否则你的代码将不能编译通过,事实上我们有很多方案可以解决这个问题。

1、在枚举成员和字符串之间创建一个映射(可以使用数组或哈希表)
2、将枚举成员 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 类继承自 Attribute,它包含一个类型为String的属性Description,下面将该属性关联到枚举 EmployeeType 的所有成员上。

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() 方法

public static string GetEnumDescription(Enum enumObj)
{
    System.Reflection.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
}
而且我还得创建一个 EnumDescription 的派生类 ManagerAttribute,跟提供两个价格信息(最高和最低薪水值)

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 关联到所有枚举成员上,为了让代码的可读性更强,给 ManagerAttributes 的所有属性都附了值。

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 属性值的通用方法,让它支持所有数据类型,使用C# 2.0 中的泛型(Generics)很容易办到

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)
    {
        System.Reflection.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
    {
        System.Reflection.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);

抱歉!评论已关闭.