Search code examples
c#retenrules

How to do optimal write rule definition in NRules


The code of NRules SimpleRule define the following rule:

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));
    }
        ...
}

I am wondering why the conditions are seperate pareameters in stead of just using && operator i.e. will the following have the same effect?

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));
    }
        ...
}

Solution

  • The two definitions should do the same thing. The Collect method expects an array of Expression<Func<T, bool>>. The first one splits it up into 3 separate conditions, while the second uses only one condition (And-combined).

    I think it is a matter of taste, which one you prefer. But with the first one it is much cleared which conditions are relevant and you can easily remove or add conditions (via commenting //).