Policy activity allows more natural processing of business rules than the general procedural execution of rules. It uses forward chaining mechanism of inference engines. This is based on artificial intelligence concepts. Using this mechanism, the engine might evaluate these rules more than once if it these rules are dependent upon each other.
Rule Execution in Forward Chaining System:
There are two methods of reasoning for inference rules in Artificial Intelligence. They are forward chaining and backward chaining. The backward chaining is goal driven. Windows WF uses forward chaining for the execution of its rule sets. This is a data driven mechanism.
Which rule to pick up first: All rules are available for rule engine as a collection of rules. For equal priority rules, they are picked up in the ascending order of their names.
After processing each rule, the WF rule engine checks which rule to process next based on the determined dependencies between rules. It picks up the highest priority rule and executes it. It is possible that it processes the same rule again based on the criteria of rule selection.
Rule Set in Policy Activity:
The rules in the Policy activity are defined with the help of Rule Sets:
This activity allows us to define various rules connected to each other in the form of rule sets. These rule sets might be dependent or independent of each others. Two rules are considered dependent if one modifies a property which another rule is dependent upon.
It must be remembered that any rule might be disabled anytime. If a rule is disabled, then runtime would not be executing that rule.
Structure of a Rule in Rule Set:
A rule has following structure in Policy Activity:
If CONDITION then
ACTION1
ELSE ACTION2
The values for Condition, Action1 and Action2 are provided when a rule is defined. Remember that Action2 is not a required Action. They are basically code blocks which require technical coding knowledge.
Dependencies between Rules:
As we have discussed, multiple rules can be defined in a Policy activity. These rules might be dependent upon each other in different ways.
Since this is a forward chaining mechanism, there must be a way for system to determining dependencies between rules. There are three options to specify such dependencies. They are as follows:
1. Implicit:
As its name implies, the engine automatically finds out about the dependencies between rules. If a rule is modifying a property in its action that is part of condition of another rule then they are considered dependent. It must be remembered that it is basically the direct modification of properties that we are talking about. If a rule is calling a method which is modifying some property that condition of another rule is dependent upon, rule engine would not be able to find such dependencies.
2. Attribute based:
This is used when actions are using some methods which are modifying some properties that another rule is dependent upon. A method must specify the properties it is modifying with the help of attributes. There are following attributes available for such purpose.
1. RuleRead: When a method is using some property but not modifying it.
2. RuleWrite: When a method is modifying some property.
3. RuleInvoke: When this method is calling some other method which might be using or updating the value of some property.
E.g. if a method, named myMethod, is modifying a property, named myProperty, then it is defined as follows:
[RuleWrite(“myProperty”)]
Public void myMethod() {…}
You would be glad to know that you can use wildcard (*) if you want to specify that a method is modifying more than one properties. E.g. a method is modifying all the properties of customer class. It should be specified as [RuleWrite(“Customer/*”)]
3. Explicit:
Attribute based dependencies specification works in all scenarios except when you don’t have access to the code directly and you are using libraries which are modifying some properties. Since you can not modify the code of libraries for introduction of attributes, there is another feature provided for dependencies specification. It is based on explicitly specifying that this method call could modify some field / property. Update statement is used for this purpose. E.g. a method is used which modifies some property myProperty. This has to be specified like this:
this.myMethod()
update(myProperty)
Priority of Rules:
Priority affects in the evaluation of rules when more than one rule is part of a Policy Activity. These rules are evaluated in the descending order of their priorities. The rules with the same priority are executed in the alphabetical order of their names.
The value of Property must be an integer value. It can not be blank.
What if two rules have same priority?
If two rules have same priority then they are executed in the ascending order of their names. Two rules can not have same names. Remember that their appearance in the Rule Set Editor might not be the same as their order of execution.
Chaining of rules:
This is used to control the forward chaining behavior of rule sets. There are three options possible:
1. Full Chaining:
This is the default forward chaining behavior. This would keep tract of all dependencies between rules and evaluates and re-evaluates rules as per the requirements.
2. Sequential:
This option specifies to the engine that it evaluates every rule once and only once no matter any THEN or ELSE action is executed or not. Only priority is considered for the execution of rules.
3. Explicit updates only:
This is extreme control of chaining. This means to avoid all the implicit and attribute based dependencies. Only those dependencies are considered which have explicit Update statement.
Reevaluation Options:
There are two reevaluation options available for rules. They are as follows:
1. Never: This rule is evaluated only once and never be reevaluated based on the execution of rules executed after this rule. If the rule has not yet executed any THEN or ELSE action, it would still be re-evaluated.
2. Always: All rules, which are executed after this rule, will cause reevaluation of this rule.
Rules file:
If you want to have a look at how these rules are managed by Windows WF, open the rules file in your workflow. This is an xml file. As we have seen that the rules in the Policy Activity are defined in the form of rule sets. The skeleton definition of these rule sets in the workflow file is as follows:
<RuleDefinitions>
<RuleDefinitions.RuleSets>
<RuleSet>
<RuleSet.Rules>
<Rule>
<Rule.ThenActions>
<RuleStatementAction>
</RuleStatementAction>
</Rule.ThenActions>
<Rule.Condition>
<RuleExpressionCondition>
</RuleExpressionCondition>
</Rule.Condition>
</Rule>
</RuleSet.Rules>
</RuleSet>
</RuleDefinitions.RuleSets>
</RuleDefinitions>
Though this seems that, since this is based on xml, we can update these rules whenever we want without needing any recompilation again, but it is not that easy. All the code statements still are code statements which are referenced in this xml.
Halt Command:
HALT Command: It is a special statement which can be provided in the action list of any rule. This statement halts the execution of the rule set. After this statement is executed, no more rule from the rule set are executed.