我喜歡地圖規則。 你也可以在你的枚舉值上加一個自定義屬性。
例如:
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