When I go out and I talk to partners and customers about WF there is a lot of interest in leveraging the rules capabilities. Whether they are looking to have declarative rules inside their workflows, or by executing complex policy against a set of custom objects in any .NET code, there's a lot about rules to like.
I'm working on a sample which uses Rules to validate a Sudoku board, namely from Sudoku sample on the community site.
Now, there are plenty of complicated ways to determine if a Sudoku configuration is valid (and plenty of other ways to solve the Sudoku [including Don Knuth's Dancing Links approach to solve the Exact Cover problem for Sudoku]). But I'm going to focus on a relatively simple, validate rows, validate columns and validate boxes approach.
I'm going to need to operate my rules across a collection, namely a 2-dimensional array of integers. So, how do we operate across a collection?
Searching in the SDK, which is full of fantastic information, leads us to the "Using Rule Conditions in Workflows" section. In there you'll find the "Collection Processing" section that outlines how you can process over collections. It goes a little something like this (in descending priority):
Now, I have an array. Sure, I can get the enumerator from this, but I'd like to use an integer which I update to navigate through this array. This is important to me because I need to know where I am at in the process (the 1st element or the 5th element) in order to convey some relevant information out to the user.
For an array, we've got a little simpler pattern that incorporates some shortcuts, we could certainly do the approach above, and if we're sure of our incoming variables (namely the integer we use to keep track of our current position), we can do it in one rule. The rule looks like this:
if (i < ItemCount) THEN total = total + items[i] i = i + 1 <== this is what causes the rule to then re-evaluate itself due to chaining
if (i < ItemCount)
total = total + items[i]
i = i + 1 <== this is what causes the rule to then re-evaluate itself due to chaining
We have an initial rule, with a priority of 2 set to initialize i to 0. But wait, you may say, why does my class need to have this iterator. The short story, it doesn't, but you have to have it somewhere, so what I have done is create a rule helper class that contains an instance of the class I am interested in executing the ruleset on, along with whatever "support" variables I need. So, we use the rules engine chaining capabilities in our second rule, with priority 1, to force the re-execution of the rule as many times as we need. And thus, we iterate over our simple array, the collection we all start from!
Ok, you may say, but I want a sample of this working when I truly have a collection of custom objects. Let's do that as well. There's one tricky thing to note here: The Intell-sense like interface sometimes makes it hard to consistently case stuff. I spent a while chasing down why my ruleset was only executing twice when I had 30 objects in the list. Consistently casing things made that work right. The problem that I had was that the final rule, was cased to the member variables, all lower case. The rule where I set the current item to the next one in the stack was cased to the property. When I changed this, because the symbol names didn't match up (the facts, if you will) the engine did not know to re-execute my final rule, which in turn did not call update to cause everything to re-evaluate. I also had some odd behavior with a typed IEnumerator (from System.Collection.Generics), but it appears now that things are working fine after discovering and correcting the cAsInG issues. So, like I said, pay attention to your casing, especially if you follow a variableName / VariableName naming scheme for C# private variables and properties.
Also, check out Moustafa's post on how you can use rule tracing to see what rules executed, this is what clued me in to what was and wasn't happening.
In the meantime, you can check out the sample that I have posted to the community site here.
Steps to get the application to work:
I look forward to your feedback!
I thought I understood how the WF Rules iterated over a collection. Isn't that always how it goes - you