基于分组c#

时间:2018-12-08 15:54:42

标签: c# wcf design-patterns

我需要有关WCF服务设计的帮助。我有一个从数据库返回Products的方法。在用户界面上,我可以使用以下选项对产品进行分组:

  1. 否/默认分组:返回所有Products的列表。

  2. 制造商分组:根据特定制造商返回所有Products的列表。

  3. 应纳税分组:返回所有应纳税的Products的列表。

下面是我的整个回复结构:

<ResponseStruct>
  <!-- Grouping is done on product-->
    <ProductList>
        <Product>
            <Name></Name>
            <Taxability>
                <Value></Value>
            </Taxability>
            <ManufacturerList>
                <Manufacturer>
                    <Name></Name>
                    <City></City>
                </Manufacturer>
                <Manufacturer>
                    <Name></Name>
                    <City></City>
                </Manufacturer>
            </ManufacturerList>
        </Product>
        <Product>
            <Name></Name>
            <Taxability>
                <Value></Value>
            </Taxability>
            <ManufacturerList>
                <Manufacturer>
                    <Name></Name>
                    <City></City>
                </Manufacturer>
                <Manufacturer>
                    <Name></Name>
                    <City></City>
                </Manufacturer>
            </ManufacturerList>
        </Product>
    </ProductList>

  <!-- Grouping is done on taxability of product-->
    <TaxabilityList>
        <Taxability>
            <Value></Value>
            <ProductList>
                <Product>
                    <Name></Name>
                    <ManufacturerList>
                        <Manufacturer>
                            <Name></Name>
                            <City></City>
                        </Manufacturer>
                        <Manufacturer>
                            <Name></Name>
                            <City></City>
                        </Manufacturer>
                    </ManufacturerList>
                </Product>
                <Product>
                    <Name></Name>
                    <ManufacturerList>
                        <Manufacturer>
                            <Name></Name>
                            <City></City>
                        </Manufacturer>
                        <Manufacturer>
                            <Name></Name>
                            <City></City>
                        </Manufacturer>
                    </ManufacturerList>
                </Product>
            </ProductList>
        </Taxability>
        <Taxability>
            <Value></Value>
            <ProductList>
                <Product>
                    <Name></Name>
                    <ManufacturerList>
                        <Manufacturer>
                            <Name></Name>
                            <City></City>
                        </Manufacturer>
                        <Manufacturer>
                            <Name></Name>
                            <City></City>
                        </Manufacturer>
                    </ManufacturerList>
                </Product>
                <Product>
                    <Name></Name>
                    <ManufacturerList>
                        <Manufacturer>
                            <Name></Name>
                            <City></City>
                        </Manufacturer>
                        <Manufacturer>
                            <Name></Name>
                            <City></City>
                        </Manufacturer>
                    </ManufacturerList>
                </Product>
            </ProductList>
        </Taxability>
    </TaxabilityList>

  <!-- Grouping is done on manufacterur-->
    <ManufacturerList>
        <Manufacturer>
            <Name></Name>
            <City></City>
            <ProductList>
                <Product>
                    <Name></Name>
                    <Taxability>
                        <Value></Value>
                    </Taxability>
                </Product>
                <Product>
                    <Name></Name>
                    <Taxability>
                        <Value></Value>
                    </Taxability>
                </Product>
            </ProductList>
        </Manufacturer>
        <Manufacturer>
            <Name></Name>
            <City></City>
            <ProductList>
                <Product>
                    <Name></Name>
                    <Taxability>
                        <Value></Value>
                    </Taxability>
                </Product>
                <Product>
                    <Name></Name>
                    <Taxability>
                        <Value></Value>
                    </Taxability>
                </Product>
            </ProductList>
        </Manufacturer>
    </ManufacturerList>
</ResponseStruct>

现在,我通过以下方式解决了这个问题: 首先,我确定了要响应的单个Model类。

1.  Product
-   Name
-   Taxability
-   IList<Manufacturer>
2.  Taxability
-   Value
-   IList<Product>
3.  Manufacturer
-   Name
-   City
-   IList<Product>

对于用例1(默认分组),我将ManufacturerList和TaxabilityList标记都关闭以作为响应,并仅从数据库填充ProductList对象。对于用例2(基于制造商分组),我将产品ProductList和TaxabilityList保留为响应状态,仅填充ManufacturerList对象。

用例3的示例响应:

<ResponseStruct>
  <ProductList/>
  <ManufacturerList/>
  <TaxabilityList>...</TaxabilityList>
</ResponseStruct>

需要帮助:

上面是我创建的示例,用于演示我的问题。实际上,有5种分组选项,用户输入请求可以进行2级分组(他可以按请求将其发送到分组对象数组中),这会导致20种可能的响应格式。

  

我的实现存在问题。我有三层   服务,当我收到输入时,我在查看后设置了一个标志   输入验证层下的输入请求中的分组属性,其中   稍后由业务层使用,在此我格式化基于响应的分组   输入的属性,由于很多“如果”,这变得很混乱   语句,所以我创建了不同的响应格式化程序类,   实现一个接口,但是我担心的是我创建了太多   类,因为我必须构建多种响应格式(20)。

我是否可以阅读任何主题的设计模式或建议以解决问题?

我可能会以完全错误的方式来解决我的问题,因此将不胜感激。

2 个答案:

答案 0 :(得分:2)

我认为这个问题的复杂性之一在于每个组表示具有不同的属性。例如,当您按制造商分组时,您将具有分组者的名称/地址,但是当您按税率分组时, d具有值。我对此进行了思考,我将提出的解决方案很可能会导致UI发生轻微变化,但它可能会为您提供一些用于处理此类数据的类。

首先,从现在开始,一切都是GroupedCollection。用户是否未选择任何内容都没有关系,仍然按分组没有任何内容。我们的GroupedCollection类应该是集合的集合。

内部集合将具有详细信息-外部集合将仅是集合。

因此,将其放入代码中-看起来像这样。

// This class is responsible from carrying information + items belonging to a single group.
public class SingleGroupCollection<N> : Collection<N>
    {
        //
        // The property bag is where you carry the per-group data.
        // Like your grouped-by Manufacturer <"name", "G. Manufacturer">
        // You should expose methods so you could retrieve all of its 
        // keys-values and display the group-specific data in your UI.

        Dictionary<string, string> PropertyBag;
        public SingleGroupCollection()
        {
             // Classic .Add() / .Remove() methods should work since 
             //   we inherit from a Collection.
        }
    }

现在我们有了一个SingleGroupCollection<Product>类-我们需要一些东西来容纳所有组。我们可以在下面创建类:

/*
    This class will hold all of the data that you're tranferring across.
    Depending on the grouping type - which I've imagined to be an enum, 
    you can set to be only 1 group / vs multiple groups,
    fill the class as you see fit with the information that you've retrieved from the DB.
 */
public class GroupedCollection<N> : Collection<SingleGroupCollection<N>>
    {
        public GroupedCollection()
        {
            // default
        }

        public GroupedCollection(GroupingType[] type)
        {
            // set types
            // set collection
        }
    }

这样,您可以在支持多个GroupingType的同时扩展/重用GroupedCollection类,并且仍然具有单一的响应类型。

你怎么看?

答案 1 :(得分:0)

根据所使用的UI框架,可以实现客户端分组。这样,该服务就不必关心所有不同的分组用例,并且可以按原样返回未分组的数据。

如果必须对服务器端进行分组,那么我将为每种情况构建不同的方法,但要使用共同的合同。一些pseduo代码:

interface MyService
{
    IList<Product> GetProducts();
    IList<Group<Product>> GetProductsGroupedByTaxability();
    IList<Group<Product>> GetProductsGroupedByManufacturer();
}

class Group<T>
{
    public String Name { get; set; }
    public IList<T> Items { get; set; }
}

如果我正确理解了这个问题,那么您的真正问题是分组必须是动态的并且是多层次的(例如:按制造商分组,或者按制造商分组,然后按应纳税性分组)如果可以合理地将客户限制在两个层次上分组,那么以下合同可能对您有用。

interface MyService
{
    IList<Product> GetProducts();
    IList<Group<Product>> GetGroupedProducts(Field level1);
    IList<Group<IList<Group<Product>>> GetGroupedProducts(Field level1, Field level2);
}

enum Field { Manufacturer, Taxability }

高度嵌套的泛型难以快速读取,但是对于单层生成的响应类似。

<Groups>
    <Group>
        <Name>Massey Fergusson</Name>
        <Items>
            <Product>...</Product>
            <Product>...</Product>
            <Product>...</Product>
        </Items>
    </Group>
    <Group>
        <Name>John Deere</Name>
        <Items>
            <Product>...</Product>
            <Product>...</Product>
            <Product>...</Product>
        </Items>
    </Group>
</Groups>

对于两个级别:

<Groups>
    <Group>
        <Name>Massey Fergusson</Name>
        <Items>
            <Group>
                <Name>20%</Name>
                <Items>
                    <Product>...</Product>
                    <Product>...</Product>
                </Items>
            </Group>
            <Group>
                <Name>0%</Name>
                <Items>
                    <Product>...</Product>
                    <Product>...</Product>
                </Items>
            </Group>
        </Items>
    </Group>
    <Group>
        <Name>John Deere</Name>
        <Items>
            ...
        </Items>
    </Group>
</Groups>