Calling a Policy Programmatically
With the test complete, right-click Version 1.0 of the policy, click "Publish," and then click "Deploy" to deploy the policy to the repository as shown in Figure 23
. Note that after deployment, you can no longer modify the policy by editing existing rules, removing rules, or adding new ones. Because the policy has been deployed, you cannot change it; instead, you must create a new version of the policy to modify it.
Recall that although your ExecuteCustomerCheckOutDiscountAmountShouldBeTenPercent unit test compiled (see Listing 3) the last time you exercised it, it failed because the CustomerCheckOut method skeleton wasn't yet implemented, and therefore, the DiscountPercentage is zerojust as it was before the test ran.
Figure 23. Deploying Policies: The You can deploy policies to the repository directly from the Business Rules Composer, or by using the BRE Deployment Utility (not shown).
Figure 24. Integrating the BRE: Programming with the Microsoft BRE is as simple as adding a reference to the Microsoft.BusinessRules.dll assembly.
Jumping back into Visual Studio, in the Acme.RetailOperations project, right-click References and add a reference to the Microsoft.RulesEngine.dll, which contains everything you need to integrate the Microsoft BRE into your application. The Microsoft.RuleEngine.dll assembly resides in the C:\Program Files\Microsoft BizTalk Server 2006\ folder as shown in Figure 24.
To focus on enforcing the business rule, I won't show any other implementation details, but for completeness, you certainly might expect a real-world implementation of the CustomerCheckOut method to carry out additional chores, such as checking inventory, calculating shipping charges, and authorizing a credit card.
After adding the reference to the Microsoft.RulesEngine.dll, add the following using statement to the PurchaseService.cs file:
shows the code for the PurchaseService class, which acts as your primitive application layer.
|Figure 25. Successful Unit Test: After integrating the BRE policy into the application layer, unit tests are critical to ensure that corresponding actions behave as expected.|
You need to split the Customer and PurchaseOrder into two separate facts because the BRE will work with each fact separately. You can accomplish this by simply creating an object array and adding the Customer instance and decomposed PurchaseOrder instance to the fact array.
With the facts ready, instantiate a Policy and provide the name of the policy in the constructor. Note that you can also provide a specific version of the policy, butif omittedthe BRE will always use the newest policy version. Now, call Execute on the Policy instance, passing in the facts array.
When the BRE finishes executing the policy, it sets the DiscountPercentage property on the instance of the Customer class to 10 percent. The PurchaseService maintains a reference to that instance. If you now re-run the ExecuteCustomerCheckOutDiscountAmountShouldBeTenPercent unit test, it should pass with flying colors as shown in Figure 25.
While this is a very simplistic implementation of a purchasing application layer, you can probably already see that the loose coupling between the application layer and the business rules is powerful indeed. Not only do you have less code to write (you've harnessed the power of a fully featured rule-based engine with two lines of code), but the discount policy is free to evolve with the needs of the business.
For example, suppose a decision was made to increase or decrease the discount amount for preferred members, or even to eliminate the rule altogether? Implementing this change would simply be a matter of updating the Customer Discounts Policy within the Business Rules Composer, testing the condition, and deploying a new policy version, all without changing a single line of code!