我喜欢地图规则。
您还可以在枚举值上添加自定义属性。
例如:
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