NRules:如何在模块中组织规则以及如何与其他规则一起启用/禁用

时间:2018-10-25 10:38:54

标签: nrules

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

  1. 某些规则确定是否应应用其他规则组。例如(用伪代码):“当vehicle的类型为car时,应用所有适用于car的规则。”

  2. 某些规则将确定应排除特定规则。

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

这意味着规则应组织成在执行过程中以某种方式启用/禁用的模块。我想到了一些解决方案:

  • 标记规则并使用“议程”过滤器来过滤规则,具体取决于用于启用/禁用规则的服务。我已经尝试过了,但并没有达到我想要的效果,因为引擎没有对服务进行更改。

  • 添加确定是否应应用规则的规则,并在每个规则的“匹配”条件中使用此规则。这会导致每个规则中有很多重复的代码,我不太喜欢。

  • 在规则执行期间加载新的规则组。我不确定如何执行此操作,如果是建议的方法或应该预期的方法。

有正确的方法去做我想做的事吗?

1 个答案:

答案 0 :(得分:1)

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

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

您提到的一项要求是什至不加载不需要的规则。如果确实如此,我认为您正处于第二组解决方案之内。该引擎没有任何内置机制可以简化这种情况,因此您必须自己构建它。正如我所看到的,您需要将一组元规则加载到他们自己的会话中,以计算条件,然后在以后将其用于加载特定规则。例如,如果汽车是汽车,您将有一个与汽车匹配的规则,然后在会话中插入“汽车”标签。其他一些元规则可能会计算更多标签。 然后,您将使用计算出的标记来加载其他规则集,例如,加载具有这些计算出的标记中的任何一个的所有规则,然后将它们编译到单独的会话中,然后针对这些加载的规则运行事实。这些规则将需要编译并加载到新的会话中,因为一旦编译后,会话工厂将是不可变的,因此无法向其添加任何新规则。

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

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

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

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

然后,您的汽车特定规则如下:

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

在您产生汽车事实的规则被触发之前,甚至不会评估任何特定于汽车的规则。