将枚举映射到“子枚举”

Jen*_*112 5 .net c# enums

我有一个包含Products的数据库。这些产品已分类,具有类别子类别

例如:

Product p1 = new Product()
{ 
    Category = Category.Fruit, 
    Subcategory = Subcategory.Apple 
 };
Run Code Online (Sandbox Code Playgroud)

我的问题是我想根据类别限制子类别。

下面的示例应该是不可能的:

Product p2 = new Product()
{ 
    Category = Category.Fruit, 
    Subcategory = Subcategory.Cheese 
};
Run Code Online (Sandbox Code Playgroud)

此外,我希望能够返回一个字符串数组(匹配每个Category枚举),每个字符串都有一个对应子类别的数组。

我已经思考了一段时间,但没有提出任何建议,也没有在线找到任何解决方案。

有什么建议?

pli*_*nth 7

我喜欢地图规则。您还可以在枚举值上放置自定义属性。

例如:

public enum Subcategory {
    [SubcategoryOf(Category.Fruit)]
    Apple,
    [SubcategoryOf(Category.Dairy)]
    Emmenthaler
}
Run Code Online (Sandbox Code Playgroud)

这要求您编写一个SubcategoryOfAttribute类(有关MS指南,请参见此处)。然后,您可以编写一个验证程序,该验证程序可以查看任何子类别并从中获取合法的父类别。

相对于地图而言,这样做的优势在于,在声明中很好地阐明了关系。

缺点是每个子类别最多只能有一个父类别。

我对此很感兴趣,因此我将其存根。首先是属性:

[AttributeUsage(AttributeTargets.Field)]
public class SubcategoryOf : Attribute {
    public SubcategoryOf(Category cat) {
        Category = cat;
    }
    public Category Category { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

然后我们做一些模拟枚举

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
}
Run Code Online (Sandbox Code Playgroud)

现在我们需要一个谓词来确定子类别是否与类别匹配(注意:如果需要,您可以具有多个父类别-您需要修改属性和该谓词以获取所有属性并检查每个属性。

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后输入产品类型进行测试:

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; }
}
Run Code Online (Sandbox Code Playgroud)

测试代码:

Product p = new Product(Category.Electronics, Subcategory.Mp3Player); // succeeds
Product q = new Product(Category.Dairy, Subcategory.Apple); // throws an exception
Run Code Online (Sandbox Code Playgroud)