基于任意逻辑将对象减少为类别

时间:2011-12-07 00:44:23

标签: c# oop categories idioms

这个问题可能是主观的。我不确定它是属于这里还是Programmers

假设我有一个数据类型X(想想从关系数据库构建的业务对象)。我的最终目标是在报表的表格中表示此类型的许多实例,每个实例都在几个不同的标题之一。

根据管理层传递的任意逻辑选择显示对象的标题,任何完成公司软件开发的人都会熟悉:

示例:

If the instance has a FooID of 6 and a BarFactor of < 0.5, place it under the "Borked" heading.

If the Weight is > 0, and the CreatedDate is before Midnight but after 3PM, and today is not the 3rd Wednesday of the month, the object should be categorised as "Fluffy".

我的问题:是否有一个常见的习惯用于获取X的实例,将一个潜在的令人头痛的逻辑量应用于实例的状态,并从结果中获取类别/字符串/任意值这个逻辑?


到目前为止,我的想法是:

  1. 一个接受X并返回String的函数。我可以很容易地看到这变成了Megamoth,并且随着需求的不断修改而保持不变。

  2. 定义Heading抽象类型和工厂函数,它为Heading实例提供正确重载的ToString方法。我认为这种技术会受到与想法相同的问题的困扰。 1。

  3. 一个功能层次结构,每个功能都会将问题进一步分解,直到我们到达正确的标题。

  4. 例如:

    public String GetHeading(X x) 
    {
        if (x.Weight > 0)
            return WeightGreaterThanZero(x);
        else if (x.Weight < 0)
            return WeightLessThanZero(x);
        else
            return WeightIsZero(x);
    }
    

    三个“权重”函数将测试更多条件,直到我们得到一个值。我在这里看到的问题是我们需要跟踪哪个函数被调用。 FooIDIs6函数需要知道它是否被WeightIsZero或其他函数调用,否则任何先前的决定都可能毫无意义。我们最终得到WeightIsGreaterThanZero_FooIDIs6_GrandmotherIsOlderThan100等等。

2 个答案:

答案 0 :(得分:1)

我不确定这完全适用于你想要实现的目标,但每当我们遇到这种“乐趣”时,我们最终会为业务用户提供一个用户界面来定义他们的规则,然后写得足够用于将规则应用于特定对象的代码。

例如,在我们的一个应用程序中,我们允许用户指定一组条件,当评估为true时,将生成用户定义的输出。

为此,我们在数据库中为IF语句的每个部分存储一条记录。每个记录指定类中的属性名称,比较操作(&lt;,=,&lt;&gt;等),比较值,语句是否开始或结束组(即parens),以及当前如何语句与下一个(AND或OR)连接。

所以你会有

Heading Record (Parent record, which defines the heading to be used)
  Heading Selector (Child records which define the if statement)

我们还可以在父记录中支持用户定义的优先级,这样如果给定记录有多个匹配,则用户有责任通过正确应用优先级来确定最佳匹配。

在运行时,您只需构建一个语句来评估用户输入的条件。我们使用反射,因此我们不必硬编码属性名称。

此外,在更适合在SQL中执行选择逻辑的情况下,可以使用相同的配置代码生成SQL语句。

我们广泛使用这种机制,并发现它是满足客户频繁和多样化需求的一种非常强大的方法。

答案 1 :(得分:0)

一组接受X的类别类怎么样,并指出它是否是该X的正确类别?类似的东西:

var categories = new Category[] { new FooCategory(), new BarCategory(), new FluffyCategory() };

foreach( var x in myListOfXs ) {
  var cat = categories.FirstOrDefault(c => c.Matches(x));
  if( cat != null ) {
    x.Category = cat.Name;
  }
}