Hour 12 Working with the WF RuleSet

What You’ll Learn in This Hour:

Image   WF rule overview

Image   RuleSet creation through the Policy activity

Image   RuleSet dependency calculations

Image   Calling methods from rules and dependency attributes

Image   External RuleSet application

Image   Configuring a workflow to access an external RuleSet

So far we have looked at executing single rules that are bound to an activity. The structure of a common rule is this: if (ItemQuantity < 0) CancelOrder();. This matches the way rules are used in traditional code. We will now look at The WF RuleSet, another form of rules much more closely aligned with rules engines. Rule sets in general differ from traditional rules in two ways:

Image   In addition to providing evaluational criteria, they provide the corresponding action. In the preceding example, a Rule in a RuleSet will contain both the if (ItemQuantity < 0) and the CancelOrder(); action.

Image   They frequently contain a number of interrelated rules (a set) that process in conjunction to perform a function such as calculating a price or a promotional amount. If you looked into the source code of a promotional or pricing calculation, for example, you are likely to find many if, else, while, switch, and other statements that churn in tandem to return an answer.

In WF, a RuleSet is always stored in a .rules file. Declarative Rule Conditions are also stored in .rules files. The only WF rules not stored in .rules files are Code Conditions. The two main advantages to storing rules in .rules files are that they are more accessible to tools and they can be loaded and/or changed at runtime.

In this hour you learn to create a WF RuleSet. Then you will learn to call methods from a Rule within a RuleSet. You will use the External RuleSet Toolkit that permits .rules files to be stored, versioned, and accessed at runtime from a SQL database. Finally, you will learn to trace RuleSet execution using standard .NET tracing.

Creating the RuleSet

This section begins with an overview of RuleSet terminology and then takes you through creating a RuleSet.

RuleSet Terminology and Project Ruleset

As previously stated, a RuleSet contains one or more rules. Each RuleSet rule contains the following attributes:

Image   A Name property that provides the rule with a name.

Image   A Condition property that holds the evaluation criteria (for example, if (itemqty > 0)).

Image   A Then Actions property that holds the actions performed if the Condition evaluates to true.

Image   An optional Else Actions property that holds the actions performed if the rule Condition evaluates to false.

Image   An optional Priority property that can override the order that individual rule executes in.

Image   A Reevaluate property that determines whether the rule should be automatically reevaluated if a value it depends on is changed by another rule (this is referred to as forward or full chaining in rules-engine speak and is described shortly).

Image   RuleWrite and RuleRead attributes that can be added to Rule methods to explicitly state dependencies on a WF rule when WF is incapable of inferring them itself.

You will create a RuleSet in this hour that has three rules: DiscountPercent, TotalOrderAmount, and YearlySales. These rules are all dependent on each other. Table 12.1 shows each rule, its evaluational criteria, and its execution semantics.

TABLE 12.1 Sample Rules

Image

A WF RuleSet is processed through a forward (or full) chaining rules engine, which means it can reprocess dependent rules. The neat part is that WF can do much of this automatically via clever CODEDOM programming (a .NET serialization capability), in contrast to forcing the developer to attribute the dependencies. For example, the yearly sales must be updated with the current order amount, but the discount must be factored in or else yearly sales will be erroneously inflated. The next steps demonstrate how WF executes the sample RuleSet.

1.   Evaluate the Condition property on the YearlySales rule because it contains the highest Priority. It evaluates to false.

2.   Evaluate the Condition on the DiscountPercent rule because it contains the second highest Priority. It evaluates to true, so the ThenActions updates the discount attribute.

3.   Evaluate the Condition on the TotalOrderAmount rule because it is next and it is dependent on the discount changed in the prior rule. It evaluates to true, so execute its ThenActions.

4.   Reevaluate the YearlySales rule because it depends on the total attribute contained in the preceding rule.

Creating the Project

1.   Create a new blank solution (Other Project Types, Visual Studio Solutions) named RulesetSolution in the C:SamsWf24hrsHoursHour12Rules directory.

2.   Add a Sequential Workflow Console Application project named RulesetProject to the solution.

3.   Open Program.cs and add the following code below the WaitHandle.WaitOne(); line to pause the host:

               Console.WriteLine("Press enter to continue");
               Console.Read();

4.   Rename Workflow1.cs to RulesetWorkflow.cs in the Solution Explorer.

5.   Add the following member variables to the RulesetWorkflow code-behind file below the constructor:

               double discountThreshold = 2000.00;
               double subtotal = 3000.00;
               double total = 0.00;
               double discount = 0.00;
               double totalYearlySales = 0.00;
               double originalTotalYearlySales = 5000.00;

Creating the RuleSet via the Policy Activity

The workflow will be sparse. It consists of a Policy activity that contains a RuleSetReference property that a RuleSet is bound to. Therefore a RuleSet, through the Policy activity, can be modeled into workflows.

1.   Drag and drop a Policy activity onto the workflow.

2.   Click its RuleSetReference property and click the ellipsis.

      You should see the Select Rule Set dialog shown in Figure 12.1.

FIGURE 12.1 Select Rule Set dialog.

Select Rule Set dialog.

3.   Click the New button to add a new RuleSet.

Adding the DiscountPercent Rule

1.   Click the Add Rule button to add the first rule (a rule within the RuleSet).

     You should see the Rule Set Editor dialog as shown in Figure 12.2.

FIGURE 12.2 Rule Set Editor dialog.

Rule Set Editor dialog.

2.   Name the rule DiscountPercent.

3.   Set its priority to 2.

4.   Leave the default Reevaluation (set at Always) and make sure the Active check box is checked.

5.   Enter the following in the Condition expression box:

               this.subtotal > 2000

6.   Enter the following in the ThenActions expression box (this action occurs if the rule is true):

               this.discount = 0.05

7.   Leave the ElseActions expression box empty. (Don’t click OK yet.)

Adding the TotalOrderAmount Rule

In the next steps, you add the TotalOrderAmount rule.

1.   Click the Add Rule button to add the second rule. (The first one will be displayed in the middle of the form.)

2.   Name the rule TotalOrderAmount.

3.   Set its Priority to 1.

4.   Leave the default Reevaluation as Always and make sure Active is checked.

5.   Enter the following in the Condition expression box:

               this.discount > 0

6.   Enter the following in the ThenActions expression box:

               this.total = (1 - this.discount) * this.subtotal

7.   Enter the following in the ElseActions expression box:

               this.total = this.subtotal

Adding the YearlySales Rule

In the next steps, you add the YearlySales rule.

1.   Click the Add Rule button to add the third rule. (The second rule will be displayed in the middle of the form.)

2.   Name the rule YearlySales.

3.   Set its Priority to 3.

4.   Leave the default Reevaluation as Always and make sure Active is checked.

5.   Enter the following in the Condition expression box:

               this.total != 0

6.   Enter the following in the ThenActions expression box:

               this.totalYearlySales = this.originalTotalYearlySales + this.total

7.   Leave the ElseActions expression box empty.

8.   Your Rule Set Editor dialog with completed rules should now look like Figure 12.3.

FIGURE 12.3 Rule Set Editor dialog with completed rules.

Rule Set Editor dialog with completed rules.

9.   Click the OK button.

10.   You should now be returned to the Select RuleSet form where the rule set you just added should be displayed.

11.   Make sure your newly added RuleSet is highlighted and click the Rename button.

12.   Chang the rule set name to MyRuleSetDeclarative in the Rename RuleSet dialog.

13.   Click the OK button twice to leave both dialogs.

Running the Workflow

Follow the next steps to add a Code activity to print the results to the console and run the workflow.

1.   Drag and drop a Code activity onto the workflow below the Policy activity to display the results.

2.   Double-click the Code activity and enter the following in its handler:

               Console.WriteLine("Subtotal {0}", subtotal);
               Console.WriteLine("Total {0}", total);
               Console.WriteLine("Discount {0}", discount);
               Console.WriteLine("Total Yearly Sales {0}", totalYearlySales);
               Console.WriteLine("Original Total Yearly Sales {0}",
                       originalTotalYearlySales);

3.   Press F5 to run the workflow and you should receive the results shown in Figure 12.4.

FIGURE 12.4 RuleSet execution results.

RuleSet execution results.

The key is that the TotalYearlySales is 7,850, which reflects the discounted total order amount. WF automatically infers the dependency of the total in the YearlySales and TotalOrderAmount rules. In a simple sample with three rules this is not a great help; however, in many more complex pricing, promotional, and trading rules that contain 10s, 100s, or even 1,000s of rules, this automated dependency processing can be immensely useful. In the upcoming section that shows how to call methods from a rule, you will see what happens when dependencies are not observed.

Monitoring the RuleSet

It is important that you understand exactly how rules in a WF RuleSet are processed. Because although it is useful, the automated reevaluation could be disastrous if it calculated differently than you expected. Both WF tracking and standard .NET tracing can be used to trace RuleSet execution.

Tracking provides the Rule Name and Condition evaluation result. Tracing, depending on the level of detail requested, first enumerates the evaluation and then the execution. It provides Rule Names, then and else condition effects (described shortly), the rules that executed, and the conditional evaluation results for the executed rules.

This exercise covers tracing. RuleSet tracking is covered in Hour 13, “Learning to Track Workflows.”

Adding RuleSet Tracing

An application configuration file must be added and the level of tracing specified to determine what RuleSet information will be traced.

Follow the next steps to configure the workflow to be traced.

1.   Add an App.config file by right-clicking the project, choosing Add, New Item, selecting the Application Configuration File template.

2.   Click the Add button. (Leave the default App.Config name.)

3.   Insert the following snippet between the Configuration opening and closing elements to specify the maximum tracing information be collected:

               <system.diagnostics>
                    <switches>
                         <add name="System.Workflow.Activities.Rules" value="All" />
                    </switches>
               </system.diagnostics>

4.   Your App.config file should look like Listing 12.1.

LISTING 12.1 App.Config File Configured to Trace


               <?xml version="1.0" encoding="utf-8" ?>
               <configuration>
                 <system.diagnostics>
                      <switches>
                           <add name="System.Workflow.Activities.Rules" value="All" />
                      </switches>
                 </system.diagnostics>
               </configuration>

Evaluating Pre-Execution Results

Follow the next steps to run the workflow and evaluate the results.

1.   Press F5 to run the workflow; you should see RuleSet evaluation results in the Output Window following all the loading statements (Click View, Output if your Output Window is not shown). The content is described immediately following its display.

                  Verbose: 0 : Rule Set "MyRuleSet": Rule "YearlySales" Condition
sdependency:
                       "this/total/"
                  Verbose: 0 : Rule Set "MyRuleSet": Rule "YearlySales" THEN side-
effect:
                        "this/totalYearlySales/"
                  Verbose: 0 : Rule Set "MyRuleSet": Rule "DiscountPercent" Condition
dependency:
                        "this/discountThreshold/"
                  Verbose: 0 : Rule Set "MyRuleSet": Rule "DiscountPercent" Condition
dependency:
                        "this/subtotal/"
                  Verbose: 0 : Rule Set "MyRuleSet": Rule "DiscountPercent" THEN
side-effect:
                        "this/discount/"
                  Verbose: 0 : Rule Set "MyRuleSet": Rule "TotalOrderAmount"
Condition dependency:
                        "this/discount/"
                  Verbose: 0 : Rule Set "MyRuleSet": Rule "TotalOrderAmount" THEN
side-effect:
                        "this/total/"
                  Verbose: 0 : Rule Set "MyRuleSet": Rule "TotalOrderAmount" ELSE
side-effect:
                        "this/total/"
                  Verbose: 0 : Rule Set "MyRuleSet":Rule "DiscountPercent" THEN
actions trigger
                        rule "TotalOrderAmount"
                  Verbose: 0 : Rule Set "MyRuleSet":Rule "TotalOrderAmount" THEN
actions trigger
                        rule "YearlySales"
                  Verbose: 0 : Rule Set "MyRuleSet": Rule "TotalOrderAmount" ELSE
actions trigger
                        rule "YearlySales"

The pre-execution evaluation data contains the following (this is WF’s plan for executing the RuleSet before it actually does so):

Image   The trace level, which is Verbose in our case. (Try setting it to different levels to see how it affects the trace output, if you want.)

Image   Each rule’s conditional dependency, the data attribute evaluated in the condition.

Image   Each rule’s THEN side effect, the data updated by the Then action.

Image   Each rule’s ELSE side effect, the data updated by the Then action.

Image   The rules triggered by each rule are shown. For example, the DiscountPercent rule triggers the TotalOrderAmount rule because a change in the discount necessitates adjusting the order amount.

Image

The System.Workflow.Activtities.Rules and workflow instance information was omitted for clarity.

Evaluating Post-Execution Results

The post-execution results are immediately below their pre-execution counterparts next (their content is described immediately following):

Rule Set "MyRuleSet": Executing
Rule Set "MyRuleSet": Evaluating condition on rule "YearlySales".
Rule Set "MyRuleSet": Rule "YearlySales" condition evaluated to False.
Rule Set "MyRuleSet": Evaluating condition on rule "DiscountPercent".
Rule Set "MyRuleSet": Rule "DiscountPercent" condition evaluated to True.
Rule Set "MyRuleSet": Evaluating THEN actions for rule "DiscountPercent".
Rule Set "MyRuleSet": Evaluating condition on rule "TotalOrderAmount".
Rule Set "MyRuleSet": Rule "TotalOrderAmount" condition evaluated to True.
Rule Set "MyRuleSet": Evaluating THEN actions for rule "TotalOrderAmount".
Rule Set "MyRuleSet": Rule "TotalOrderAmount" side effects enable rule
"YearlySales" reevaluation.
Rule Set "MyRuleSet": Evaluating condition on rule "YearlySales".
Rule Set "MyRuleSet": Rule "YearlySales" condition evaluated to True.
Rule Set "MyRuleSet": InstanceId Evaluating THEN actions for rule "YearlySales".

The execution results data contains the following:

Image   A row that states that execution has begun.

Image   The condition of the first rule is evaluated.

Image   The results of the first rule are output (false in our case).

Image   Any rules that evaluate to true trigger their respective Then actions, as would be expected. Likewise, Else actions are triggered when rules evaluate to false.

Image   The most interesting result (which is boldface in the preceding code) takes place when the TotalOrderAmount rule’s Then/Else action executes: it triggers reevaluation of the Yearly Sales rule. We already know this, but it is interesting to see WF’s implementation.

Image

The data before RuleSet in each line was omitted for clarity.

Calling Methods from Rules

You can call methods from the rules in a RuleSet. We will now replace Then and Else actions in the TotalOrderAmount rule to use a method to update the values instead of doing so declaratively. This requires that we attribute the method, because WF will no longer be able to automatically infer the dependency of the total attribute that is used to calculate yearly sales.

1.   Add the following method to your workflow code-beside file below the handler that displays the results:

               private void UpdateTotal()
               {
                   this.total = (1 - this.discount) * this.subtotal;
               }

2.   Click the Policy activity, click the + next to the RuleSetReference property, and click the ellipsis in the RuleSet Definition property.

3.   Click the TotalOrderAmount rule and replace the contents in the Then Actions and the Else Actions sections with a call to UpdateTotal().

4.   Your TotalOrderAmount rule should now look like Figure 12.5.

FIGURE 12.5 Calling a method from a RuleSet.

Calling a method from a RuleSet.

5.   Run the workflow and you should see the results shown in Figure 12.6 wherein the Total Yearly Sales is 0.

FIGURE 12.6 RuleSet processing results with undetected dependency.

RuleSet processing results with undetected dependency.

This does not match earlier processing. The reason is that the YearlySales rule is not invoked because the Total field is now updated inside a method and WF cannot automatically detect this. WF only detects members manipulated in the method signature. Those updated in the body must be explicitly noted, as shown next.

Attributing Methods to Detect Dependency

In the next subsection you attribute a method called from an action and in the following you do so for a method called from a condition. In both cases, the reason for doing so is to explicitly state dependency.

Attributing a Method Called from an Action

Follow the next steps to attribute the UpdateTotal method to explicitly state dependencies from a method from a Rule action.

1.   Add the following attributes above the UpdateTotal method that inform the RuleSet that the total field is written to and the discount field is read from:

               [RuleWrite("total")]
               [RuleRead("discount")]

2.   The method should now look like this:

               [RuleWrite("total")]
               [RuleRead("discount")]
               private void UpdateTotal()
               {
                  this.total = (1 - this.discount) * this.subtotal;
               }

3.   Run the workflow and you should see results that match the original declarative results.

Image

If a dependent value is updated in a method that is called from a method that was called by a rule, use the RuleInvoke attribute to denote indirect dependencies because of method calls.

Attributing a Method Called from a Condition

So far you have called a method from a Rule action, which performs a write or an update. You can also call methods from a Rule condition. These methods can be attributed to reflect which values are read inside of them so they will reevaluate.

Follow the next steps to attribute the UpdateTotal method to explicitly state dependencies from a method from a Rule condition.

1.   Add the following attributed method to your workflow code-beside file, below the previous method.

               [RuleRead("subtotal")]
               [RuleRead("discountThreshold")]
               private bool CheckDiscount()
               {
                   return this.subtotal > this.discountThreshold;
               }

2.   Now you must edit the DiscountPercent rule to use this method.

3.   Edit the RuleSet and select the DiscountPercent rule.

4.   Replace the contents in the Condition property with the call to CheckDiscount(). (It will automatically insert this. before the method name when you save.)

      Your RuleSet (and specifically the DiscountPercent rule) should now look like Figure 12.7.

FIGURE 12.7 RuleSet processing results with undetected dependency.

RuleSet processing results with undetected dependency.

5.   Run the workflow again and you should get the correct results with all values updated as expected. The dependent values in the methods are detected and the rules reevaluate accordingly.

Using the External RuleSet Application

By default, a RuleSet is stored in a .rules file and is bound to one workflow (as a resource). In this exercise you will download an application that permits a RuleSet to be stored and versioned in a database. The RuleSet is then loaded and executed at runtime. The RuleSets are maintained from a Windows application that is part of the External RuleSet Toolkit. The dialogs used to maintain a RuleSet are available via an API, making a RuleSet available to any .NET 2.0 or later application. The External RuleSet Toolkit is not part of WF, but rather a community application developed by a Microsoft Program Manager. In addition to being useful, the External RuleSet application exemplifies the type of tooling being built around the WF’s XML Serialized formats:—whether XAML or .rules. It also shows how to create custom runtime services and to call the rules dialogs from a .NET app.

The next lists contains the items you will perform to download and use the External RuleSet application.

1.   Download the External RuleSet application.

2.   Use the demo workflow included with it.

3.   Store the RuleSet you created earlier in the External RuleSet application.

4.   Configure a new workflow to access the RuleSet stored in the External RuleSet application.

Downloading the External RuleSet Application

Perform the next steps to download and install the External RuleSet application.

1.   Create a directory to hold the application, such as ExternalRuleSet.

2.   Download the External RuleSet application from http://wf.netfx3.com/files/folders/rules_samples/entry309.aspx.

3.   Run the self-extracting .exe file and browse to the directory you just created.

4.   View the Setup.cmd file and change the database settings if necessary. The default setting is to localhostSQLExpress. To use it with SQL Server and localhost, delete the SQLExpress reference in the file.

5.   The command calls a SQL script that creates a database named rules, which holds the RuleSet information.

Running the Sample Workflow

To ensure that the External RuleSet application is functioning and to see how it works, run the sample workflow solution included with the External RuleSet application. This workflow executes a RuleSet even though it does not contain a policy activity. It achieves this through a custom activity that mediates communication between the database and the .rules file. The custom activity binds to a .rules file in a database rather than in the current workflow.

Follow the next steps to run the sample workflow that comes with the External RuleSet application.

1.   Open the RuleSetToolkitUsageSample solution by navigating to the C:ExternalRuleSetRuleSetToolkitUsageSample directory and clicking the RuleSetToolkitUsageSample.sln file.

2.   Pause the host by adding the requisite code to Program.cs, as you did earlier in the hour.

3.   Press F5 to run the sample; you should see the results shown in Figure 12.8 in the command window. (If not, verify that the External RuleSet application was installed properly.)

FIGURE 12.8 Sample External RuleSet application processing results.

Sample External RuleSet application processing results.

4.   The custom (Policy) activity on the workflow is configured as shown in Figure 12.9.

FIGURE 12.9 Custom Policy activity configuration.

Custom Policy activity configuration.

5.   The DiscountRuleSet is the name of a RuleSet stored in the rules database by the External RuleSet application.

6.   If the different versions of the RuleSet are stored in the External RuleSet application, the specific version can be specified in the MajorVersion and MinorVersion properties. If they are both set to 0, the latest version will always be retrieved.

Uploading Rules to the External Database

Follow the next steps to upload the RuleSet created earlier in this hour to the External RuleSet application. This way these rules can be edited outside of the workflow they were created with, versioned, and changed at runtime.

1.   Open the ExternalRuleSetToolkit solution by navigating to the C:ExternalRuleSet directory and clicking the ExternalRuleSetToolkit.sln file.

2.   Make sure the RuleSetTool project is set as the startup project and then run the project.

3.   You should see the RuleSet Browser dialog with DiscountRuleSet RuleSet included with the sample application already loaded, as shown in Figure 12.10.

FIGURE 12.10 RuleSet Browser with sample workflow loaded.

RuleSet Browser with sample workflow loaded.

4.   Click Data, Import, browse to the RulesetWorkflow.rules file in the C:SamsWf24hrsHourHour12RulesRulesetSolutionRulesetProject directory and select the file. This is the project with the Policy activity and RuleSet you created in an earlier exercise.

5.   The MyRuleSet RuleSet will be displayed in the RuleSet Selector dialog. The dialog allows for selection when there are multiple RuleSets stored in a workflow, which is not the case with our sample. Your screen should now look like Figure 12.11.

FIGURE 12.11 RuleSet Selector with sample workflow loaded.

RuleSet Selector with sample workflow loaded.

6.   Click OK and the MyRuleSetDeclarative RuleSet is now added to the list of RuleSets in the RuleSet Browser form, as shown in Figure 12.12.

FIGURE 12.12 RuleSet Browser with sample workflow loaded.

RuleSet Browser with sample workflow loaded.

7.   Version 1.0 of the MyRuleSetDeclarative RuleSet should be selected.

8.   Select Rule Store, Save to upload the MyRuleSetDeclarative RuleSet to the rules database.

Adding the Custom Policy Activity to the Toolbox

To make the custom Policy activity available to all workflows, follow the next steps to add it to the toolbox.

1.   Go back to the RulesetProject project you created earlier and open the workflow in design mode.

2.   Right-click the Toolbox, select Choose Items. (This may take a while.)

3.   Select the Activities tab.

4.   Browse to the PolicyActivities.dll file in the C:ExternalRuleSetPolicyActivitiesinDebug directory.

5.   Ensure that the PolicyFromService activity is selected in the Choose Toolbox Items dialog and click OK.

6.   You should now see the PolicyFromService activity on the Toolbox.

Preparing the Workflow to Use External Rules

Follow the next steps to add another workflow project to your RulesetSolution solution. You will configure this workflow to use the PolicyFromService activity.

1.   Right-click the RuleSetSolution in the Solution Explorer, choose Add, New Item, select Project, select the Sequential Workflow Console application template, and name it RuleSetExternalWorkflowsTester.

2.   Reference the C:ExternalRuleSetPolicyActivitiesinDebugPolicyActivities.dll and C:ExternalRuleSetPolicyActivitiesinDebugRuleSetService.dll projects, which are needed to execute the PolicyFromService activity.

3.   Add the following statement to the using statement declaration section at the top of Program.cs.

               using RuleSetServices;

4.   Add the following statement above the line that starts the workflow instance to Program.cs.

               workflowRuntime.AddService(new RuleSetService());

5.   Add an App.config file by right-clicking the project, choosing Add New Item, and selecting the Application Configuration File template.

6.   Click the OK button. (Leave the default App.Config name.)

7.   Insert the following snippet between the Configuration opening and closing elements to specify your connection string (substitute for your settings as appropriate):

               <connectionStrings>
                 <add name="RuleSetStoreConnectionString"
connectionString="Initial
                       Catalog=Rules;Data Source=localhost;Integrated Security=SSPI;"
                       providerName="System.Data.SqlClient"/>
    </connectionStrings>

Configuring the Workflow to Use External Rules

Follow the next steps to add a PolicyFromService activity to the workflow. As with the standard Policy activity, the PolicyFromService binds a workflow to a RuleSet, but does so to one stored in the Ruleset database in contrast to a .rules file stored with the workflow.

1.   Drag and drop a PolicyFromService activity onto the workflow. This is the custom activity you added to the Toolbox a couple of steps ago.

2.   Click the PolicyFromService activity and set its RuleSetName (not the activity name) property to MyRuleSetDeclarative to configure it to use the RuleSet you added to the External Rule application.

3.   Add the member variables used by the RuleSet to the workflow code-beside file below the constructor, as shown:

               double discountThreshold = 2000.00;
               double subtotal = 3000.00;
               double total = 0.00;
               double discount = 0.00;

               double totalYearlySales = 0.00;
               double originalTotalYearlySales = 5000.00;

4.   Add the custom methods used by the RuleSet below the member variables as shown (your rules are stored in the external application, but not your custom methods):

               [RuleWrite("total")]
               [RuleRead("discount")]
               private void UpdateTotal()
               {
                   this.total = (1 - this.discount) * this.subtotal;
               }

               [RuleRead("subtotal")]
               [RuleRead("discountThreshold")]
               private bool CheckDiscount()
               {
                   return this.subtotal > this.discountThreshold;
               }

Running the Workflow with External Rules

Add a Code activity to display rule processing results and run the workflow.

1.   Drag and drop a Code activity below the PolicyFromService activity onto the workflow and add the following to its handler:

               Console.WriteLine("Workflow name {0}", this.Name);
               Console.WriteLine("Subtotal {0}", subtotal);
               Console.WriteLine("Total {0}", total);
               Console.WriteLine("Discount {0}", discount);
               Console.WriteLine("Total Yearly Sales {0}", totalYearlySales);
               Console.WriteLine("Original Total Yearly Sales {0}",
                      originalTotalYearlySales);

2.   Add code to Program.cs to pause the host.

3.   Press F5 to run the workflow, and you should receive the results shown in Figure 12.13. (If you choose F5, remember to pause the host with a Console.Read() statement.)

FIGURE 12.13 Custom workflow processed from RuleSet loaded from the External Ruleset application.

Custom workflow processed from RuleSet loaded from the External Ruleset application.

Summary

This hour demonstrated WF’s RuleSet capabilities, which are a collection of interrelated rules. WF’s automatic dependency processing was covered. You learned to monitor the execution of rules. Then the ability to call methods and custom attribute them when the automated dependency checking no longer suffices was covered. Finally, the External RuleSet application was demonstrated, which shows how to centrally manage and operate RuleSets. In addition it previews WF’s XML capability to work in conjunction with XML tools and rehosting the rules designers.

Workshop

Quiz

1.

What WF activity is used to bind a RuleSet to a workflow?

2.

What is the difference between a RuleSet and a traditional code-based rule?

3.

What advantage do rules stored in .rules files offer?

4.

Does WF provide forward-chaining support?

5.

Can WF detect interrule dependencies within a RuleSet?

6.

How are rule dependencies within method bodies handled?

7.

What is the structure of a rule in a RuleSet?

Answers

1.

Policy.

2.

A RuleSet contains multiple rules and corollary actions to perform updates.

3.

They can be changed at runtime using Dynamic Update, and tooling can be constructed, such as the External RuleSet application to centrally store, manage, and load them at runtime.

4.

Yes.

5.

Yes, in some cases. It will detect them in declarative rules and within method signatures.

6.

By attributing the methods with RuleRead and RuleWrite attributes.

7.

Condition, ThenAction, ElseAction.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.93.12