I was looking at a simple rule engine http://netmatze.wordpress.com/2012/01/22/building-a-rule-engine-in-c/ and I'm doing something very similar to this. I have two classes that look like:
class A
{
public List<B> ListB { get; set; }
}
Class B
{
public int ID { get; set; }
}
With my rule set looking like:
List<Rule> rules = new List<Rule>{
new Rule("listB", ExpressionType.Loop, 1, "ID")
};
I'm trying to build the expression to basically look at class A property listB, loop it camparing each item's ID property to see if at least one equals 1. I'm having trouble on how to do this. I currently have something like (I have hard coded values set in this, but it will eventually be changed to be generic as much as possible). This expression does not work, I get compile exceptions:
var parameterExpression = Expression.Parameter(typeof(A));
var listB = MemberExpression.Property(parameterExpression, "ListB");
var leftOperand = MemberExpression.Property(Expression.Parameter(typeof(B)), "ID");
var rightOperand = Expression.Constant(1); //1
var found = Expression.Variable(typeof(bool), "found");
return Expression.Lambda<Func<T, bool>>(
Expression.Block(
listB,
found,
Expression.Loop(
Expression.Block(
Expression.IfThen(
Expression.Equal(
leftOperand,
rightOperand
),//equal
Expression.Assign(
found,
Expression.Constant(true)
)//set to true
)
)//block
)//loop
),
A
).Compile();
I'll end up calling the rule set against my object like so:
Engine ruleEngine = new Engine();
var compiledRules = rules.Select(r => ruleEngine.CompileRule<A>(r)).ToList();
var result = compiledRules.All(rule => rule(objA));
My questions are:
- How do I get this function to return true/false if any of the list items matched the condition.
- How do you prevent the Expression.Loop to stop looping once all list items are compared (and none of them matched)?
Thanks for any help.