Search code examples
c#retenrules

NRules: match a collection


I'm trying to figure out the BRE NRules and got some examples working but having a hard time to match a collection.

IEnumerable<Order> orders = null;

When()
    .Match<IEnumerable<Order>>(o => o.Where(c => c.Cancelled).Count() >= 3)
    .Collect<Order>(() => orders, o => o.Cancelled);

Then()
    .Do(ctx => orders.ToList().ForEach(o => o.DoSomething()));

Basically what I want is if there are 3 orders cancelled then do some action. But I can't seem get a match on a collection, single variables do work.

The program:

var order3 = new Order(123458, customer, 2, 20.0);
var order4 = new Order(123459, customer, 1, 10.0);
var order5 = new Order(123460, customer, 1, 11.0);

order3.Cancelled = true;
order4.Cancelled = true;
order5.Cancelled = true;

session.Insert(order3);
session.Insert(order4);
session.Insert(order5);

session.Fire();

What am I doing wrong here?


Solution

  • With the 0.3.1 version of NRules, the following will activate the rule when you collected 3 or more canceled orders:

    IEnumerable<Order> orders = null;
    
    When()
        .Collect<Order>(() => orders, o => o.Cancelled)
            .Where(x => x.Count() >= 3);
    Then()
        .Do(ctx => orders.ToList().ForEach(o => o.DoSomething()));
    

    Update:

    For posterity, starting with version 0.4.x the right syntax is to use reactive LINQ. Matching a collection will look like this:

    IEnumerable<Order> orders = null;
    When()
        .Query(() => orders, q => q
            .Match<Order>(o => o.Cancelled)
            .Collect()
            .Where(x => x.Count() >= 3));
    Then()
        .Do(ctx => DoSomething(orders));