基于类的枚举实现
使用类和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
库提供了一个基类来创建此类基于类的枚举,并提供了一些基本功能,例如 Parse
和 NHiberante
用户类型。
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
库。