Declarative RuleSets
In addition to using the rules editor to create markup-based rulesets, rules can be created programmatically using the RuleDefinitions class. This class has two collection properties named Conditions and RuleSets.
The following example shows how to programmatically create a RuleSet. In this example, a RuleSet object is first created before rules are added to it. Following this, reference expressions are created in order to connect the rules with instance data present in the class that implements the BuildRuleSet method. The discount, orderValue and customerType references are fields defined within the class. The next step is to create the residential discount rule using objects from the System.CodeDom namespace. The rule that is being created, checks if the order value is greater than 500 and if the customer type is residential. If the condition is true, the discount that is applied is 5%. Next, a similar rule is created using different values to indicate a discount that is applied if the customer is a business customer type. Both of these rules are added to the initial RuleSet.
private RuleSet BuildRuleSet()
{
RuleSet discountRuleSet = new RuleSet("DiscountRuleSet");
// Define property and activity reference expressions.
CodeThisReferenceExpression thisRef = new CodeThisReferenceExpression();
CodeFieldReferenceExpression discountRef = new CodeFieldReferenceExpression(thisRef, "discount");
CodeFieldReferenceExpression orderValueRef = new CodeFieldReferenceExpression(thisRef, "orderValue");
CodeFieldReferenceExpression customerTypeRef = new CodeFieldReferenceExpression(thisRef, "customerType");
CodeTypeReferenceExpression customerEnumRef = new CodeTypeReferenceExpression(typeof(CustomerType));
// Add the residential discount rule.
// IF OrderValue > 500 AND CustomerType = Residential
// THEN Discount = 5%
Rule resDiscountRule = new Rule("ResidentialDiscountRule");
discountRuleSet.Rules.Add(resDiscountRule);
// Define the first predicate test: OrderValue > 500.
CodeBinaryOperatorExpression resOrderValueTest = new CodeBinaryOperatorExpression();
resOrderValueTest.Left = orderValueRef;
resOrderValueTest.Operator = CodeBinaryOperatorType.GreaterThan;
resOrderValueTest.Right = new CodePrimitiveExpression(500);
// Define the second predicate test: CustomerType = Residential.
CodeBinaryOperatorExpression resCustomerTypeTest = new CodeBinaryOperatorExpression();
resCustomerTypeTest.Left = customerTypeRef;
resCustomerTypeTest.Operator = CodeBinaryOperatorType.ValueEquality;
resCustomerTypeTest.Right = new CodeFieldReferenceExpression(customerEnumRef, "Residential");
// Join the two predicates into a single condition.
CodeBinaryOperatorExpression resCondition = new CodeBinaryOperatorExpression();
resCondition.Left = resOrderValueTest;
resCondition.Operator = CodeBinaryOperatorType.BooleanAnd;
resCondition.Right = resCustomerTypeTest;
resDiscountRule.Condition = new RuleExpressionCondition(resCondition);
// Add the rule action: Discount = 5%.
CodeAssignStatement resDiscountAction = new CodeAssignStatement(discountRef, new CodePrimitiveExpression(5));
resDiscountRule.ThenActions.Add(new RuleStatementAction(resDiscountAction));
// Add the business discount rule.
// IF OrderValue > 10000 AND CustomerType = Business
// THEN Discount = 10%
Rule busDiscountRule = new Rule("BusinessDiscountRule");
discountRuleSet.Rules.Add(busDiscountRule);
CodeBinaryOperatorExpression busOrderValueTest = new CodeBinaryOperatorExpression();
busOrderValueTest.Left = orderValueRef;
busOrderValueTest.Operator = CodeBinaryOperatorType.GreaterThan;
busOrderValueTest.Right = new CodePrimitiveExpression(10000);
CodeBinaryOperatorExpression busCustomerTypeTest = new CodeBinaryOperatorExpression();
busCustomerTypeTest.Left = customerTypeRef;
busCustomerTypeTest.Operator = CodeBinaryOperatorType.ValueEquality;
busCustomerTypeTest.Right = new CodeFieldReferenceExpression(customerEnumRef, "Business");
CodeBinaryOperatorExpression busCondition = new CodeBinaryOperatorExpression();
busCondition.Left = busOrderValueTest;
busCondition.Operator = CodeBinaryOperatorType.BooleanAnd;
busCondition.Right = busCustomerTypeTest;
busDiscountRule.Condition = new RuleExpressionCondition(busCondition);
CodeAssignStatement busDiscountAction = new CodeAssignStatement(discountRef, new CodePrimitiveExpression(10));
busDiscountRule.ThenActions.Add(new RuleStatementAction(busDiscountAction));
return discountRuleSet;
}
To create a RuleDefinitions object and associate it with a workflow, add the RuleSet shown earlier as follows:
RuleDefinitions definitions = new RuleDefinitions();
definitions.RuleSets.Add(BuildRuleSet());
this.SetValue(RuleDefinitions.RuleDefinitionsProperty, definitions);
To use the RuleSet with a PolicyActivity activity, create a new RuleSetReference using the name of the RuleSet as the constructor parameter as follows:
private void InitializeComponent()
{
this.CanModifyActivities = true;
// Create the Policy activity.
this.discountPolicy = new PolicyActivity();
this.discountPolicy.Name = "advancedDiscountPolicy";
this.discountPolicy.RuleSetReference = new RuleSetReference("DiscountRuleSet");
// Define the workflow.
this.Activities.Add(this.discountPolicy);
this.Name = "DiscountPolicyWorkflow";
this.CanModifyActivities = false;
}
private PolicyActivity discountPolicy;
A similar method is used for using rules as activity conditions:
// This code is called by the workflow constructor.
CodeBinaryOperatorExpression check =
new CodeBinaryOperatorExpression();
check.Left = new CodeFieldReferenceExpression(
new CodeThisReferenceExpression(), "orderValue");
check.Operator = CodeBinaryOperatorType.LessThan;
check.Right = new CodePrimitiveExpression(10000);
RuleDefinitions definitions = new RuleDefinitions();
definitions.Conditions.Add(
new RuleExpressionCondition("Condition1", check));
this.SetValue(RuleDefinitions.RuleDefinitionsProperty, definitions);
// This code is called in the InitializeComponent method to populate the
// condition on an IfElseBranch activity.
RuleConditionReference condition1 = new RuleConditionReference();
condition1.ConditionName = "Condition1";
ifElseBranch1.Condition = condition1;