65.9K
CodeProject 正在变化。 阅读更多。
Home

基于类的枚举实现

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.89/5 (8投票s)

2008年1月20日

LGPL3

2分钟阅读

viewsIcon

39029

使用类和NHibernate用户类型实现的经典枚举。

引言

ClassEnum 库是一个基于类的枚举实现,用于在语言的 enum 无法胜任的场景下使用。

为什么使用 ClassEnum

C# 的枚举非常方便,但它只能有一个 string 名称,且名称中不能包含空格和特殊字符。

一个简单的例子可以说明为什么我们需要一个基于类的实现:信用卡类型。 有 4 种常见的信用卡类型:Visa、Master、American Express 和 Discover Card。 如果您使用 C# enum 来表示这些类型,您将不得不使用 AmericanExpress 和 DiscoverCard 作为 enum 名称,这在尝试显示它们时可能会很麻烦。
基于类的枚举实现很简单。 它使用类的 static 只读字段作为枚举项,并声明构造函数为 private 以确保安全。 以下是一个基于类的信用卡类型枚举示例:

    public sealed class CreditCardType {
        public static readonly CreditCardType AmericanExpress = 
                new CreditCardType("American Express");
        public static readonly CreditCardType DiscoverCard = 
                new CreditCardType("Discover Card");
        public static readonly CreditCardType Master = new CreditCardType("Master");
        public static readonly CreditCardType Visa = new CreditCardType("Visa");
        private readonly string name;
        private CreditCardType(string name) {

            this.name = name;
        }
        public override string ToString() {

            return name;
        }
    }

此基于类的实现的力量在于,如果需要,您可以添加属性甚至函数。 这里缺少的是 Enum.Parse 函数,该函数允许您从 string 解析 enum 类型。 此外,此基于类的枚举需要能够在 NHibernate 中映射。 ClassEnum 库提供了一个基类来创建此类基于类的枚举,并提供了一些基本功能,例如 ParseNHiberante 用户类型。

ClassEnum 使用起来很简单。 您可以通过继承 ClassEnumGeneric<T> 抽象类来创建您自己的基于类的枚举。 此处的 T 是您基于类的枚举的类型。

    public class CreditCardType : ClassEnumGeneric<CreditCardType>
    {
        public readonly  static CreditCardType Visa = new CreditCardType("Visa");
        public readonly  static CreditCardType AmericanExpress = new CreditCardType("American Express");
        private CreditCardType(string name):base(name) {}

    } 

现在,此 CreditCardType 自动继承了 ClassEnumGeneric 中的有用函数和属性。

// static parse function
CreditCardType.Parse("Visa"); //returns CreditCardType.Visa
 
// static Items property that returns a collection that contains
// CredictCardType.Visa and CredictCardType.AmericanExpress
// and other CredictCardTypesif declared.
CreditCardType.Items; //returns a collection that contains

ClassEnum 实现可以更强大,因为您可以在基于类的实现中使用继承和多态。 以下是一个示例:

  public class CreditCardType : ClassEnumGeneric<CreditCardType> {
        public readonly static CreditCardType Visa = new Visa();
        public readonly static CreditCardType AmericanExpress = new AmericanExpress();
        protected CreditCardType(string name) : base(name) {}

        public abstract bool ValidateCCNumber(string ccNumber);
 
        private class Visa : CreditCardType {

            public Visa() : base("Visa") {}
            public override bool ValidateCCNumber(string ccNumber){

              //....do some Visa validation
            }
        }
 
        private class AmericanExpress : CreditCardType {

            public AmericanExpress() : base("American Express") {}
            public override bool ValidateCCNumber(string ccNumber){

              //....do some AmericanExpress validation
            }
        }
    }

现在,您希望使用 ClassEnum 基类的另一个主要原因是:ClassEnum 程序集还提供了一个 NHibernate 用户类型,以便您可以像映射 enum 属性一样映射您的 ClassEnum 属性。 您需要做的就是通过继承 ClassEnum 程序集中的通用 ClassEnumUserType 基类来声明一个 NHibernate 用户类型。

  public class CreditCardTypeUserType : ClassEnumUserType<CreditCardType>{}

现在,您可以使用以下 Hbm 映射 XML 示例来映射您的属性:

 <property name="CCType" type="YourNameSpace.CreditCardTypeUserType, 
    YourAssembly" column="CCTypeEnum"/>

如何使用

ClassEnum 程序集是 MindLib 项目的一部分。 您可以下载 MindLib 源代码包,其中您将在 /src 文件夹中找到 ClassEnum.sln。 此外,在解决方案中,您还可以找到单元测试 ClassEnum.Test 项目,其中有更多的示例代码来演示如何使用此 ClassEnum 库。

© . All rights reserved.