NRules:如何在模块中组织规则并 enable/disable 与其他规则

NRules: how to organize rules in modules and enable/disable with other rules

我开始使用 NRules。以下是我正在构建的应用程序的一些关键要求的概述:

  1. 一些规则确定是否应应用其他规则组。例如(在伪代码中):"when the type of vehicle is car, apply all rules applying to cars".

  2. 一些规则会决定应该排除特定的规则。

  3. 可能有很多种vehicle;理想情况下,我不想在启动时加载所有车辆的所有规则。

这意味着规则应该组织成模块,这些模块在执行期间以某种方式enabled/disabled。我想到了一些解决方案:

是否有正确的方法来做我想做的事情?

在最高级别,有两种方法可以控制应用(甚至考虑)哪些规则:

  1. 将所有规则加载到会话中并在规则逻辑内处理它
  2. 将规则组加载到不同的会话中,并使用某种元规则将控件分派到相应的规则子集。

您提到的其中一项要求是甚至不加载您不需要的规则。如果确实如此,我认为您完全属于第二组解决方案。该引擎没有任何内置机制来促进这种情况,因此您必须自己构建它。正如我所看到的,您需要一组元规则,加载到他们自己的会话中,计算标准,您稍后将使用这些规则来加载特定规则。例如,如果车辆是汽车,您将有一个匹配车辆的规则,并将 "car" 标记插入到会话中。其他一些元规则可能会计算更多标签。 然后您将使用计算标签加载额外的规则集,例如,加载所有具有这些计算标签的所有规则,并将它们编译到单独的会话中,然后 运行 您的事实与这些加载的规则相对应。规则将需要编译并加载到新会话中,因为一旦编译,会话工厂是不可变的,因此不能向其中添加新规则。

如果您可以放宽不加载所有规则的要求,那么您还有更多选择。您已经触及了问题中的一些选项,但我认为您最好的选择是使用前向链接来实现您想要的。我个人认为这比尝试动态加载和编译规则要好。

例如,您可以有一个匹配车辆的规则,如果它是一辆汽车,并产生一个新的事实 - 汽车,稍后将使用特定于汽车的规则:

Vehicle vehicle = null;
When()
    .Match(() => vehicle, v => v.VehicleType == VehicleType.Car);

Then()
    .Yield(_ => new Car(vehicle));

那么,您的汽车特定规则将如下所示:

Car car = null;
When()
    .Match(() => car)
    //...

None 的汽车特定规则甚至会被评估,直到产生汽车事实的规则被触发。