Building a rule engine in c# (part 2: extending the rule engine to handle collections)

In my blog post about building a rule engine in c# i wrote about the core implementation of a rule engine. In this seconde post i will extend the rule engine so that it can handle collections of rules and collections of items to validate against the rules. To do so i have to extend the RuleEngine class and i have to introduce a RuleValidator class. With the extension of the RuleEngine the following code is possible:

ProcessingEngineDatabase

RuleLoader ruleLoader = new RuleLoader();
Rule firstRule = ruleLoader.Load(1);
Rule secondRule = ruleLoader.Load(2);
Rule thirdRule = ruleLoader.Load(3);

RuleEngine ruleEngine = new RuleEngine();
var ruleFuncs = ruleEngine.CombineRules<Person>(
    new Rule[] { firstRule, secondRule, thirdRule });

That means I load first, second and third rule and combine them to a array of rules. To do so i implemented the CombineRules method in the RuleEngine class.

public Func<T, bool>[] CombineRules<T>(Rule[] rules)
{
    List<Func<T, bool>> list = new List<Func<T, bool>>();
    foreach (Rule rule in rules)
    {
        if (string.IsNullOrEmpty(rule.PropertyName))
        {
            ExpressionBuilder expressionBuilder = new ExpressionBuilder();
            var param = Expression.Parameter(typeof(T));
            Expression expression = expressionBuilder.BuildExpression<T>(rule.Operator_, rule.Value, param);
            Func<T, bool> func = Expression.Lambda<Func<T, bool>>(expression, param).Compile();
            list.Add(func);
        }
        else
        {
            ExpressionBuilder expressionBuilder = new ExpressionBuilder();
            var param = Expression.Parameter(typeof(T));
            Expression expression = expressionBuilder.BuildExpression<T>(rule.PropertyName, rule.Operator_, rule.Value, param);
            Func<T, bool> func = Expression.Lambda<Func<T, bool>>(expression, param).Compile();
            list.Add(func);
        }
    }
    return list.ToArray();
}

The i use the new RuleValidator to validate one or a collection of objects against that defined rules.

RuleValidator ruleValidator = new RuleValidator();
bool result = ruleValidator.ValidateRulesAll(person, ruleFuncs);
result = ruleValidator.ValidateRulesAny(person, ruleFuncs);

As we see there are two methodes to validate the person object against the rules. The ValidateRulesAll method returns true if all rules are passed by the overtaken person object. The ValidateRulesAny method return true if any rule is passed by the overtaken person object. It is also possible to validate not only one person object but a collection of person objects.

Person person1 = new Person() { Name = "Mathias", Age = 36, Children = 2 };
Person person2 = new Person() { Name = "Anna", Age = 33, Children = 2 };
bool result = ruleValidator.ValidateRulesAll(new Person[] { person1, person2 }, ruleFuncs);
result = ruleValidator.ValidateRulesAny(new Person[] { person1, person2 }, ruleFuncs);

In this case both methodes (ValidateRulesAll and ValidateRulesAny) return true because the test persons both pass all three rules. The implementation of the RuleValidator class is very simple. It is just a foreach loop that calls the overtaken rules with the overtaken values. In the ValidateRulesAll method it checks if all rules are passed and then returns true, in the ValidateRulesAny it checks one rule after the other and if one rule is passed it returns true.

public class RuleValidator
{
    public bool ValidateRulesAll<T>(T value, Func<T, bool>[] rules)
    {
        foreach (var rule in rules)
        {
            if (!rule(value))
                return false;
        }
        return true;
    }

    public bool ValidateRulesAny<T>(T value, Func<T, bool>[] rules)
    {
        foreach (var rule in rules)
        {
            if (rule(value))
                return true;
        }
        return false;
    }

    public bool ValidateRulesAll<T>(T[] values, Func<T, bool>[] rules)
    {
        foreach (var value in values)
        {
            foreach (var rule in rules)
            {
                if (!rule(value))
                    return false;
            }
        }
        return true;
    }

    public bool ValidateRulesAny<T>(T[] values, Func<T, bool>[] rules)
    {
        foreach (var value in values)
        {
            bool validated = false;
            foreach (var rule in rules)
            {
                if (rule(value))
                {
                    validated = true;
                    break;
                }
            }
            if (!validated)
                return false;
        }
        return true;
    }
}

In this third part of the post series called Building a rule engine in c# (part 3: extending the rule engine to handle aggregations of collections) i extend the rule engine to handle aggregation for collections. In the fourth part of this blog series i write about implementing an expression evaluator to define more complex expressions Building a rule engine in c# (part 4: extending the rule engine to evaluate defined expressions) and in the fifth part building a rule engine in c# (part 5: bringing it all together) i give an overview about the usage of the ruleengine.codeplex.com project i created to bring the code parts in that post series together.


What is new in c# 5.0 – Asynchrone Programming

Today i will hold a talk about “What is new in c# 5.0 – Asynchrone Programming” at the .net usergroup south austria. The agenda is:

  • what is new in c# 5.0
  • async ctp – .net 4.5
  • task based asynchron pattern
  • async – await (Asynchronous Control Flow)
  • async intern
  • synchronisationContext in
  • Console App, Winforms App und Asp.net
  • cancellation
  • exception handling
  • combinators
  • async – await with the Windows Runtime
  • caller information

The powerpoint presentation and the examples are on my public skydrive folder:

What is new in c# 5.0 – Asynchrone Programming