如何在NRules中进行最佳写规则定义

时间:2015-06-01 10:18:20

标签: c# rete nrules

NRules SimpleRule的代码定义了以下规则:

public class PreferredCustomerDiscountRule : Rule
{
    public override void Define()
    {
        Customer customer = null;
        IEnumerable<Order> orders = null;

        When()
            .Match<Customer>(() => customer, c => c.IsPreferred)
            .Collect<Order>(() => orders,
                o => o.Customer == customer,
                o => o.IsOpen,
                o => !o.IsDiscounted);

        Then()
            .Do(ctx => ApplyDiscount(orders, 10.0))
            .Do(ctx => LogOrders(orders))
            .Do(ctx => orders.ToList().ForEach(ctx.Update));
    }
        ...
}

我想知道为什么条件是单独的pareameters而不是仅仅使用&amp;&amp;运营商,即以下会产生同样的效果吗?

public class PreferredCustomerDiscountRule : Rule
{
    public override void Define()
    {
        Customer customer = null;
        IEnumerable<Order> orders = null;

        When()
            .Match<Customer>(() => customer, c => c.IsPreferred)
            .Collect<Order>(() => orders,
                o => o.Customer == customer && o.IsOpen && !o.IsDiscounted);

        Then()
            .Do(ctx => ApplyDiscount(orders, 10.0))
            .Do(ctx => LogOrders(orders))
            .Do(ctx => orders.ToList().ForEach(ctx.Update));
    }
        ...
}

2 个答案:

答案 0 :(得分:10)

提供单个条件表达式与由'&amp;&amp;'分隔的组件之间存在差异并提供多个条件表达式。

在幕后,规则被编译到网络(rete网络)中,并且每个条件由网络中的节点表示。当多个规则共享相同的条件子集时,这些节点在网络中共享,从而产生效率(因为评估条件较少)。由于节点共享,提供多个条件表达式为引擎提供了更多优化机会。

另一个区别是条件短路。使用'&amp;&amp;'提供单个条件表达式时运算符,标准C#条件短路适用。如果第一个条件为假,则不评估第二个条件。当提供多个条件时(由于引擎在不同的级别进行优化),这不一定正确。

最佳做法是使用多个条件表达式而不是带有'&amp;&amp;'的单个条件表达式。

答案 1 :(得分:1)

这两个定义应该做同样的事情。 Collect方法需要一个Expression<Func<T, bool>>数组。第一个将它分成3个独立的条件,而第二个只使用一个条件(And-combined)。

我认为这是一个品味问题,你更喜欢哪一个。但是第一个很清楚哪些条件是相关的,你可以轻松删除或添加条件(通过评论//)。