【问题标题】:Configurable rule based system in C#C# 中可配置的基于规则的系统
【发布时间】:2009-12-09 03:51:02
【问题描述】:

我有一个算法,它返回一个分类(字符串)列表,这取决于给算法的两个参数:一个类型变量和一个额外的类别字符串,允许将某些特殊分类添加到结果列表中。

当前的实现,由于 ifs 和 switch 语句等规则的表达,是不可读和不可扩展的。规则也是硬编码的。

代码的简化版本:

 private static List<string> DetermineTypes(Type x, object category) {
  List<string> Types = new List<string>();


  if (category is DateTime) {
    types.Add("1");
    types.Add("2");
    types.Add("3");
  } else if (category is string) {
    switch ((string)category) {
      case "A":
        Types.Add("4");
        break;
      case "B":
      case "C":
      case "D":
        Types.Add("5");
        break;
      case "":
        Types = DetermineTypesFromX(Types, x);
        break;
      default:
        Types.Add("6");
        break;
    }
  }
  return graphTypes;
}


private static List<string> DetermineTypesFromX(List<string> Types, Type x) {
  if (x.Equals(typeof(int))) {
    Types.Add("7");
  } else if (x.Equals(typeof(double))) {
    Types.Add("8");

  } else if (x.Equals(typeof(System.DateTime))) {
    Types.Add("9");
    Types.Add("10");
  }
  return Types;
}

我在想也许用 xml 指定这些会很好,这样新类型/规则就不需要更改代码,但这很可能对这种情况来说太重了。基本上,我正在尝试解决可能随时添加新“类型”的问题:常见情况是它是上述“规则”之一,而不太可能的边缘情况是新的“规则”分支可能必须被添加。

与极端情况发生的可能性和业务环境(时间表等)相比,我仍在确定使用 xml 定义的规则(或任何其他方式)使其完全动态化的工作是否值得。

但我的主要问题是如何优雅地简化上面的嵌套条件代码?也许在设计中加入更多的灵活性以提高可扩展性?

我想知道使用 F# 模式匹配的组合是否是一个合适的解决方案? (注意:以前从未使用过 F#,最近一直很好奇,所以这就是我问的原因)

【问题讨论】:

    标签: c# f# pattern-matching rules


    【解决方案1】:

    最近在以下两篇博客文章中讨论了一种称为调度表的模式,您可能会感兴趣:

    Aaron Feng

    K. Scott Allen

    【讨论】:

      【解决方案2】:

      我不会回避基于配置的选项;它通常具有不需要重建的优点。如果您不希望这样,另一个选项可能是通过属性的类型元数据。这将使为 new 类型(您编写的)添加数据变得微不足道,并且您可以(间接)通过 TypeDescriptor.AddAttributes 向现有类型(int 等)添加属性 - 只要您使用TypeDescriptor.GetAttributes 让他们再次退出;-p

      无论这是否是一个的想法......好吧,反射(和双胞胎,TypeDescriptor)可能很慢,所以如果你想在一个紧密的循环中使用它,我' d 首先看一下涉及字典的东西。

      【讨论】:

        【解决方案3】:

        您的问题可能用decision treedecision table 编码

        此外,Chris Smith 的博客中有关于决策树的帖子:

        Awesome F# - Decision Trees – Part IAwesome F# - Decision Trees – Part II

        【讨论】:

          【解决方案4】:

          我建议您查看business rules/inference 引擎。 NxBRE 周围有一个很好的社区,并且相当成熟。这可能超出了您的直接要求,但如果您希望这些规则随着时间的推移而增加复杂性,BRE 将提供一个很好的框架来控制事情。

          【讨论】:

            【解决方案5】:

            既然你提到了 F#,下面是一些与 C# 代码行为非常相似的 F# 代码:

            open System
            
            let DetermineTypesFromX(x:Type) =
                if x.Equals(typeof<int>) then
                    ["7"]
                elif x.Equals(typeof<double>) then
                    ["8"]
                elif x.Equals(typeof<DateTime>) then
                    ["9"; "10"]
                else
                    []
            
            let DetermineTypes(x:Type, category:obj) =
                match category with
                | :? DateTime -> ["1"; "2"; "3"]
                | :? string as s ->
                    match s with
                    | "A" -> ["4"]
                    | "B" | "C" | "D" -> ["5"]
                    | "" -> DetermineTypesFromX(x)
                    | _ -> ["6"]
                | _ -> []
            

            也就是说,我建议考虑使用表驱动方法来替代硬编码的 if/switch 逻辑,无论您是否将逻辑从代码中移出并放入配置文件。

            【讨论】:

              【解决方案6】:

              我遇到过类似的情况,我之前曾问过一些关于类似问题可能对您有所帮助的问题。

              我所做的系统是一个配置驱动、基于规则的动态系统。所有配置和规则都保存在数据库中。决策表是根据从数据库中检索到的值和规则动态构建的。然后在 C# 中转换和比较值。这是我问的关于dynamic decision table in C# 的问题。从数据库中检索到的question regarding dyanmically convert and compare values

              所以我最终在配置表方面得到了类似的东西(只是一个例子):

              Conditions  IsDecision LHS        Operator  RHS
              TTFF        False      PostCode   >         100
              TFTF        False      PostCode   <         10000
              FTTT        True 
              
              Note: LHS is the property name of the object.
              

              上表的简明英文:

              Condition 1 PostCode > 100      Yes Yes No  No
              Condition 2 PostCode < 10000    Yes No  Yes No
              Outcome 1                       Yes
              Outcome 2                           Yes
              Outcome 3                               Yes
              Outcome 4                                   Yes
              
              Then you have other tables/configs to determine the action for each outcome.
              

              实现的核心部分是如何动态构造决策表以及如何动态转换和比较字符串值,所有这些我在上一段中提供了具体实现的链接。我相信你可以在你的情况下应用类似的概念,我希望我已经解释了这个概念。

              其他资源:

              Martin Fowler's decision tree article.

              Luke's post on decision tree.

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2021-09-24
                • 2016-11-28
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-02-10
                相关资源
                最近更新 更多