我喜欢地图规则。 你也可以在你的枚举值上加一个自定义属性。
例如:
public enum Subcategory {
[SubcategoryOf(Category.Fruit)]
Apple,
[SubcategoryOf(Category.Dairy)]
Emmenthaler
}
这需要编写一个SubcategoryOfAttribute
类(参见here用于MS指南)。然后你可以编写一个验证器,它可以查看任何子类别并从中获取合法的父类别。
在地图上的优势在于该关系在声明中很好地阐述了出来。
缺点是每个子类别最多可以有一个父类别。
我觉得这很有趣,所以我把它取出来了。首先,属性:
[AttributeUsage(AttributeTargets.Field)]
public class SubcategoryOf : Attribute {
public SubcategoryOf(Category cat) {
Category = cat;
}
public Category Category { get; private set; }
}
然后我们做一些模拟枚举
public enum Category {
Fruit,
Dairy,
Vegetable,
Electronics
}
public enum Subcategory {
[SubcategoryOf(Category.Fruit)]
Apple,
[SubcategoryOf(Category.Dairy)]
Buttermilk,
[SubcategoryOf(Category.Dairy)]
Emmenthaler,
[SubcategoryOf(Category.Fruit)]
Orange,
[SubcategoryOf(Category.Electronics)]
Mp3Player
}
现在我们需要一个断言,以确定是否一个子类别匹配的类别(注:可以有多个父类,如果你想要 - 你需要修改属性和这个谓词来获得所有属性并检查每一个属性。
public static class Extensions {
public static bool IsSubcategoryOf(this Subcategory sub, Category cat) {
Type t = typeof(Subcategory);
MemberInfo mi = t.GetMember(sub.ToString()).FirstOrDefault(m => m.GetCustomAttribute(typeof(SubcategoryOf)) != null);
if (mi == null) throw new ArgumentException("Subcategory " + sub + " has no category.");
SubcategoryOf subAttr = (SubcategoryOf)mi.GetCustomAttribute(typeof(SubcategoryOf));
return subAttr.Category == cat;
}
}
然后你把你的产品类型来测试它:
public class Product {
public Product(Category cat, Subcategory sub) {
if (!sub.IsSubcategoryOf(cat)) throw new ArgumentException(
String.Format("{0} is not a sub category of {1}.", sub, cat), "sub");
Category = cat;
Subcategory = sub;
}
public Category Category { get; private set; }
public Subcategory Subcategory { get; private set; }
}
测试代码:
Product p = new Product(Category.Electronics, Subcategory.Mp3Player); // succeeds
Product q = new Product(Category.Dairy, Subcategory.Apple); // throws an exception
这里没有编译时的方式,除非你使用的不同的子类别组独立的枚举做到这一点。有很多不同的方法可以在运行时进行验证。 – 2014-10-20 18:04:51
继承层次结构可能更适合您的需求 – 2014-10-20 18:06:17
这是业务逻辑,而不是纯粹的技术解决方案。基本上,类别和子类别必须在某处(数据库/代码)进行定义,并且必须对其进行查找。 – 2014-10-20 18:06:37