4. Calling the Engine from a .NET Application
Application developers can use the APIs exposed by
the Business Rules Framework to call upon the BRE to execute a business
rule policy. They can assert facts to the policy that they wish to
execute. This is simply done by passing the engine an array of objects
and/or XML document as parameters.
The following code snippet illustrates how the
application developer can call the Business Rule Engine to execute the
latest version of a particular policy simply by creating a Microsoft. RuleEngine.Policy object with the particular rule name passed as a parameter to the policy's constructor.
NOTE
Calling an older version of a policy is possible
only through the Business Rules Framework APIs. The Call Rules shape in
the Orchestration Designer calls only the latest version of the policy.
To call an older version from within an orchestration, the orchestration
developer needs to use the Business Rules Framework APIs from within an
expression or an external assembly.
using Microsoft.RuleEngine;
using BTSSampleLibrary;
...
// create an instance of the policy (gets the latest version by default)
Microsoft.RuleEngine.Policy policy = null;
policy = new Microsoft.RuleEngine.Policy("Contoso Policy");
The developer can then pass the short-term facts as
well as objects that will contain return values required for the
policy's execution by packaging them in an array and passing it as a
parameter to the Policy.Execute method.
// Create an Employee fact as an example of setting up a fact
StaffMember staff = new Employee();
staff.PersonnelNumber = "123456";
staff.PrimaryRole = "Engineer";
SupportTicket orderTicket = new SupportTicket();
// create the array of short-term facts
object[] shortTermFacts = new object[3];
shortTermFacts[0] = staff;
shortTermFacts[1] = new SupportTransaction();
shortTermFacts[2] = orderTicket;
//Execute Policy
policy.Execute( shortTermFacts );
Once the rule engine instance executing the policy
returns, the developer can check for return values from the policy by
inspecting the objects whose references were passed in the array.
// Process outcome by checking the modified fact, i.e., the authorization ticket
if (orderTicket.IsAuthorized)
{
MessageBox.Show("Order approved");
}
else if (orderTicket.RequiresSupervisor)
{
MessageBox.Show("Support Supivisor Approval is Required");
}
else
{
MessageBox.Show("Order Rejected: " + orderTicket.FailureReason);
}
5. Policy Chaining
Policy chaining is the ability to call one policy
from another. Policy chaining is not natively supported through the
Business Rule Engine, but can still be accomplished through additional
coding. Essentially, a policy can call .NET code that executes another
policy.
The following steps walk through calling one policy
from another policy using a console application. It modifies the Loan
Processing Sample in the BizTalk SDK. This same sample could be used to
call the rule from an orchestration.
Create an Executer class with the following code snippet. When its Execute
method is called, the class will use the policy name that is passed to
it to assert the facts that were previously passed in via its
constructor. In this case it is passing an array to allow multiple
objects to be asserted into the engine.
using System;
using Microsoft.RuleEngine;
namespace PolicyExecutor
{
public class Executor
{
public Executor(Array passedFacts)
{
facts = passedFacts;
}
public void Execute(string policyName)
{
Policy policy = new Policy(policyName);
policy.Execute(facts);
policy.Dispose();
}
private Array facts;
public Array Facts
{
get{return facts;} set{facts = value;}
}
}
}
Create a console application with the following code snippet:
using System;
using System.Xml;
using Microsoft.RuleEngine;
using System.Collections;
using PolicyExecutor;
namespace PolicyChaining
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
string filename = "sampleLoan.xml";
string policyName = "LoanProcessing";
// Build TXD
XmlDocument xd1 = new XmlDocument();
xd1.Load(filename);
TypedXmlDocument doc1 = new
TypedXmlDocument("Microsoft.Samples.BizTalk.LoansProcessor.Case",xd1);
// Build short term fact array and provide to Executor object
object[] facts = new object[2];
PolicyExecutor.Executor executor = new PolicyExecutor.Executor(facts);
facts[0] = doc1;
facts[1] =executor;
// Call parent policy
Policy policy = new Policy(policyName);
policy.Execute(facts);
policy.Dispose();
// Write out updated XML
XmlTextWriter writer1 = new XmlTextWriter("sampleLoan_Out.xml",null);
writer1.Formatting = Formatting.Indented;
doc1.Document.WriteTo( writer1 );
writer1.Flush();
}
}
}
Set up and modify the Loan Policy SDK sample.
Run the Setup.bat file to set up the Loan Processing SDK sample.
Open the Business Rule Composer and create a new policy called LoanPolicyChained.
Copy and paste the "Income Status Rule" and the "Negation of Income Status Rule" from LoanPolicy to LoanPolicyChained.
Add a new rule to the LoanPolicy called Chain to Income Rules. Set the condition to always be true and in the action call the Execute method of the Executor class. Set the parameter to the same name as the chained policy, LoanPolicyChained. The new policies will look something like Figure 4.
Compile and run the console application to have it call the two policies.
NOTE
If the policy caller is an orchestration and not an application, the same Executor class and policies can still be used. Just replace the console app with an orchestration. One way to do this is to set up the Executor
class in an Expression shape and then call the Loan policy normally
through a Call Rules shape, while passing in the XML message and the Executor class instance. The Expression shape would include the following code:
facts = new System.Collections.ArrayList();
// Build TXD
xmlDoc = LoanMsg;
typedXmlDoc = new
Microsoft.RuleEngine.TypedXmlDocument("Microsoft.Samples.BizTalk.LoansProcessor
.Case",xmlDoc);
// Build short term fact array and provide to Executor object
facts.Add(typedXmlDoc);
executor = new PolicyExecutor.Executor(facts.ToArray());
The code also depends on four variables that can be defined within the Scope shape that is required for the Call Rules shape: executor of type PolicyExecutor.Executor, facts of type ArrayList, xmlDoc of type XmlDocument, and typeXmlDoc of type TypedXmlDocument.