zoukankan      html  css  js  c++  java
  • 對.Net中枚举(Enum)的進一步探討

    声明:
    本文内容出自:http://www.codeproject.com/useritems/DotNetEnumsNextLevel.asp
    由于本人E文菜得实在离谱,对文章的“翻译”①仅限于自娱自乐,文中用词过于牵强而且漏洞百出,强烈建议读者打开上面的链接阅读原文

    -------------------------------------------------------------

    导言

          在这篇文章里我将对.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[0as 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[0as 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);



    注释:
    ①实际上谈不上翻译,只能说是将自己的理解写出来
    http://www.cnblogs.com/yyw84/archive/2006/08/20/481900.aspx

  • 相关阅读:
    编码的使用,编码与解码
    小数据池,is和==的区别,id()
    python的内置函数
    python基本数据类型
    组合模式学习
    访问者模式
    C++ primer Plus回顾
    命令模式学习
    策略模式学习(设计模式)
    python_xlrd模块学习
  • 原文地址:https://www.cnblogs.com/godwar/p/1092936.html
Copyright © 2011-2022 走看看