0

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

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

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

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

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

  • 标记规则并使用议程过滤器根据用于启用/禁用将规则添加到议程的服务来过滤规则。我已经尝试过了,但它并没有像我希望的那样工作,因为引擎没有接收到对服务的更改。

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

  • 在规则执行期间加载新的规则组。我不知道如何做到这一点,如果它被推荐或应该预期工作。

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

4

1 回答 1

2

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

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

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

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

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

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

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

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

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

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

于 2018-11-12T03:13:42.247 回答