One of the most common ways of integrating InRule into a .NET application is to bind the rule application to a .NET assembly schema (aka .NET object model). Object-based integration provides the following advantages:
- Automated schema generation and synchronization based on .NET Assembly reflection
- Runtime state management allowing for custom business object instances to be used as rule engine state
- The ability to call .NET instance methods from rules
If you do find the need to call a .NET method from rules, you should keep in mind that the .NET Assembly State Refresh options can have a huge impact on rule execution performance.
In this blog post, I will illustrate this point by creating a rule application that is bound to a .NET assembly, add a rule that calls an instance method in that assembly, and then run some tests using our Test Suite to see how rule execution time is affected by the state refresh option.
Let’s get started!
Creating the Rule Application
InvoiceObjects.dll is a .NET assembly which is included in the Samples directory that comes with InRule. By importing and applying this assembly into a rule application, it will automatically generate the following entities:
I will add a Tax field to the LineItem entity, and calculate this tax by calling a .NET instance method called CalcSalesTax, which is in the LineItem class, shown below:
On the Schemas screen where I imported the assembly, I can select that method and then click the button shown below (pointed to by the red arrow)…
… and this opens up the .NET Assembly State Refresh options, that you’ve been anxiously waiting to hear more about!
These options tell the rule engine when it’s necessary to refresh values from the object after calling a .NET method. The default setting is to refresh all bound objects. This conservative approach is by-design to ensure the rule engine’s dependency network is aware of the changes that may have occurred within the method. Since it defaults to a full refresh, you can call your .NET methods without having to configure this option, and that’s exactly what I’m going to do for the first performance test.
After adding the Tax field and some rules to calculate the tax and calculate the total for the invoice, here is what the entities and rules look like for this rule application:
Daddy needs a new pair of shoes. Or even better, how about 5,000 pairs of shoes!
I have populated an invoice with 1,000 line items. Each line item is for 5 pairs of shoes at a unit price of $100, for a total of $500. The tax for each line item comes to $40. Therefore, the total amount for the invoice will be $540,000.
Testing (with full refresh)
I will create a test suite in irVerify and add two tests:
- A performance test to run the rules 10 times
- An assertion test to confirm that the total invoice amount came to $540,000.
Let’s run it!
The assertion test passed and the average execution time was about 2.2 seconds.
Testing (with no refresh)
The CalcSalesTax method has no side-effects, in that it does not change any properties in the object. Therefore, it is not necessary to perform any state refresh, so I’ll uncheck the option:
In general, minimizing the fields that are refreshed after the call can reduce overall processing time, especially for large bound schemas or when instance methods are called often. Let’s run the test again and see what happens. Drum roll please……………………………..
Running the tests again show that we still get the right answer, and now the average execution time was about 76 milliseconds!
Although this example involved calling a .NET method to calculate a tax, it would have been much better to calculate the tax using rules rather than a .NET method. By using rules, you can easily change how the tax is calculated without having to rebuild and redeploy a DLL. You would not need to configure state refresh options. And, you could have a business person author and maintain the rules instead of a programmer. Nonetheless, there are times when you may need to call a .NET method, and now you can see how much of an impact the .NET Assembly State Refresh options can have. To learn more about how and when to use this feature, please refer to our Authoring Help documentation.