Click here to Skip to main content
16,017,037 members
Articles / Programming Languages / C# 5.0
Tip/Trick

Dotnet Simple Rule Engine

Rate me:
Please Sign up or sign in to vote.
4.88/5 (16 votes)
16 Jun 2015CPOL2 min read 67.7K   28   25
Dotnet Simple Rule Engine

Introduction

A Business Rule Engine is a software program which executes one or more business rules on behalf of other programs. This software provides convention, grammar or UI Interface which can be used by Business Person. They can define the rules without knowing the programming. Rules can be changed dynamically without changing the application code. I found Simple Rule Engine source code on http://www.csharpopensource.com/ site, downloaded the code, compiled it on Microsoft Dotnet version 4.0 to make it compatible with current
industry standard.

Background

A brief tutorial is available at http://simpleruleengine.tripod.com/.

I am going to provide the tutorials which help in understanding and sample program to use it.

Installation

We can install the compiled package using nuget Manager. It is now available as nuget package https://www.nuget.org/packages/SimpleRuleEngine.

To install it through nuget, use PM > Install-Package SimpleRuleEngine.

Business Requirement

  • Tax Calculator application which runs on the below business logic
  • If Gross Salary is less than Rs. 500,000/- for a year, there is no tax and Net Salary is same as Gross Salary.
  • If Gross Salary is between 500,000/- and 800,000/- for a year, tax will be 20 percent of Gross Salary. Net Salary will be equal to Gross Salary minus Tax.
  • If Gross Salary is equal or greater than Rs. 800,000/- for a year, tax will be 30 percent of Gross Salary and Net Salary will be equal to Gross Salary minus Tax.

Solution

The above problem can be achieved in different and multiple ways. But I am going to use the simple rule engine to achieve this.

  1. Open Visual Studio and create a sample Console application with name Tax Calculator.
  2. Add nuget package manager to add PM> Install-Package SimpleRuleEngine.
  3. Add one class RuleExecutor to execute the above rule.
    C#
    internal sealed class RuleExecutor
        {
            public void ExecuteTaxRules()
            {
                XmlDocument rules = new XmlDocument();
    
                string directory = AppDomain.CurrentDomain.BaseDirectory + @"\TaxCalculator.xml";
    
                rules.Load(directory);  
                //model
                XmlDocument model = new XmlDocument();
                model.LoadXml(@"<Employee><GrossSalary>900000</GrossSalary>
                <HRA>50000</HRA><Tax></Tax><NetSalary>
                </NetSalary></Employee>");
             
                ROM rom = Compiler.Compile(rules);
                rom.AddModel("Employee", model);
                rom.Evaluate();
                var tax = model["Employee"]["Tax"].InnerText;
                var NetSalary = model["Employee"]["NetSalary"].InnerText;
                var message = string.Format("Tax: {0} and Net take home salary :{1}", tax, NetSalary);
                Console.Write(message);
                Console.Read();
    }
    }
  4. We can define the rule in XML format and Simple Rule engine will execute, apply the rule and will give the output.
    XML
    <?xml version="1.0" encoding="utf-8" ?>
    <RuleEngine>
    
      <Rules>
        <Rule id="RuleNoTax" desc="Rule for no tax" chainable="true"  priority="100">
          <Condition><![CDATA[ GrossSalary < 500000 ]]></Condition>
          <Actions>
            <Evaluate factId="Tax" ><![CDATA[0]]></Evaluate>
            <Evaluate factId="NetSalary"><![CDATA[ GrossSalary ]]></Evaluate>
            <Execute factId="RuleMediumTax"/>
          </Actions>
        </Rule>
     
     
        <Rule id="RuleMediumTax" desc="Rule for Medium tax" chainable="true"   priority="19">
          <Condition><![CDATA[ (GrossSalary>=500000) AND (GrossSalary<800000)]]></Condition>
          <Actions>
            <Evaluate factId="Tax" priority="11"><![CDATA[ (GrossSalary *2/10)  ]]></Evaluate>
            <Evaluate factId="NetSalary" priority="1"><![CDATA[ (GrossSalary-Tax) ]]></Evaluate>
            <Execute factId="RuleHighTax"/>
          </Actions>
    
        </Rule>
        <Rule id="RuleHighTax" desc="Rule for High tax"  chainable="true"  priority="2">
          <Condition><![CDATA[ GrossSalary>=800000]]></Condition>
          <Actions>
            <Evaluate factId="Tax" priority="2" ><![CDATA[ GrossSalary*3/10 ]]></Evaluate>
            <Evaluate factId="NetSalary" priority="1"><![CDATA[ GrossSalary-Tax ]]></Evaluate>
          </Actions>
        </Rule>
        
      </Rules>
    
      <Facts>
        <Fact id="GrossSalary" desc="Gross Salary" type="double" modelId="Employee">
          <xpath><![CDATA[ number(Employee/GrossSalary) ]]></xpath>
        </Fact>
        <Fact id="HRA" desc="House Rent Allowance" type="double" modelId="Employee">
          <xpath><![CDATA[ Employee/HRA ]]></xpath>
        </Fact>
        <Fact id="Tax" desc="Tax" type="double" modelId="Employee">
          <xpath><![CDATA[ Employee/Tax ]]></xpath>
        </Fact>
        <Fact id="NetSalary" desc="Net Salary" type="double" modelId="Employee">
          <xpath><![CDATA[ Employee/NetSalary ]]></xpath>
        </Fact>
     
     
      </Facts>
    
    </RuleEngine>
  5. Now update the Program class as shown below:
    C#
    class Program
       {
           static void Main(string[] args)
           {
               var re = new RuleExecutor();
               re.ExecuteTaxRules();
           }
       }
    
  6. 6. Compile and run the program with different values of Gross salary element in XML model.

So here, today we learnt how we can put complex business logic separate from main program and execute it separately.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
India India
Sarvesh Upadhyay is Technical Architect in Microsoft Technologies with 12 yrs of hands on experience on various domain like CRM, CMS, Inventory Management System, Telecome Billing, E-Commerce application, Retail etc.
He has indepth knowledge on Design Patterns, Asp.Net MVC, MVP , C#, JavaScript, Knockout, MS-SQL Server,Web Services,Web API, MSMQ, Saleslogix CRM, etc.

Comments and Discussions

 
QuestionIs anyone using this? Pin
RodneyLaJuan27-Dec-18 16:54
RodneyLaJuan27-Dec-18 16:54 
SuggestionRe: Is anyone using this? Pin
yogeshCJ11-Jun-19 23:15
yogeshCJ11-Jun-19 23:15 
QuestionNested Conditions in Simple Rule Engine Pin
Chirag Rajpal16-Oct-18 23:08
Chirag Rajpal16-Oct-18 23:08 
QuestionWhat does the priority mean in the rule xml? Pin
NITHIN SUHAS16-Sep-18 22:29
NITHIN SUHAS16-Sep-18 22:29 
QuestionCan we Use "Max" ? Pin
Member 1369910726-Feb-18 23:44
Member 1369910726-Feb-18 23:44 
QuestionSRE: How to use filter out in list, and, or Pin
Member 1163200523-Jun-17 0:16
Member 1163200523-Jun-17 0:16 
AnswerRe: SRE: How to use filter out in list, and, or Pin
Member 1298953021-Sep-17 0:00
Member 1298953021-Sep-17 0:00 
GeneralRe: SRE: How to use filter out in list, and, or Pin
Member 1298953021-Sep-17 0:06
Member 1298953021-Sep-17 0:06 
QuestionROM and Compiler.Compile Pin
Member 701715422-Jun-17 7:25
Member 701715422-Jun-17 7:25 
AnswerRe: ROM and Compiler.Compile Pin
Member 1163200522-Jun-17 23:56
Member 1163200522-Jun-17 23:56 
GeneralRe: ROM and Compiler.Compile Pin
Member 1039383325-Oct-17 21:31
Member 1039383325-Oct-17 21:31 
QuestionModel type Pin
Member 125952212-Mar-17 22:48
Member 125952212-Mar-17 22:48 
QuestionLoop in rule in XML Pin
Member 128450702-Feb-17 19:07
Member 128450702-Feb-17 19:07 
AnswerRe: Loop in rule in XML Pin
Member 125952213-Mar-17 0:24
Member 125952213-Mar-17 0:24 
QuestionSomething wrong... Pin
karan vidyut17-Nov-16 22:48
karan vidyut17-Nov-16 22:48 
QuestionRe: Something wrong... Pin
RodneyLaJuan27-Dec-18 17:02
RodneyLaJuan27-Dec-18 17:02 
AnswerRe: Something wrong... Pin
RodneyLaJuan29-Dec-18 8:38
RodneyLaJuan29-Dec-18 8:38 
QuestionNeeds documentation Pin
mattdunn617-Nov-16 10:24
mattdunn617-Nov-16 10:24 
AnswerRe: Needs documentation Pin
mattdunn617-Nov-16 10:43
mattdunn617-Nov-16 10:43 
QuestionHow to add OR Condition in rule Pin
Member 819864312-Aug-16 2:26
Member 819864312-Aug-16 2:26 
QuestionThis is not working Pin
Member 124530486-May-16 13:57
Member 124530486-May-16 13:57 
QuestionWould suggest learning about the system and terms if it was a professional project Pin
Member 1178413522-Jun-15 10:07
Member 1178413522-Jun-15 10:07 
There are actually certified groups for this field.
The terms and design are somewhat like designing a Database. The RI. organization, framework... of Business Rules are very important.

The book I used was:How to Build a Business Rules Engine: Extending Application Functionality through Metadata Engineering (483 Pages)

The good thing about this book is that it was written with C++ programmers in mind. However, the example (and not a small example) was built using MSAccess and VBA so the reader could actually use the examples on a desktop.

Metadata is very powerful if designed correcty. One application determines a Status for a facility in the energy industry (e.g. Well) Regulatory Database. There are many levels of Regulations for a well. A partial list includes: Environmental, Federal, State, County, Local, Tribal, Right-of-way, mineral rights, surface rights, permits (timed and conditional for Federal, St, County), surveys, accounting, Fees, ....
The data entry by various work groups, across various databases requires expertiese in each form. The triggers for work-flow (example: This if finished, the clock is ticking for two independent actions) go across work group boundries.

The challange is to create Rules that are re-usable. These rules fall into set classes. For example a Base Rule or a Buddy Rule (works in conjunction with a group of rules). This in the most basic term fits into a framework of rules. There is also the Use Interface for managing the rules. For example, the State of Utah may not receive the Survey report before the Plats are finished.

Basically, this solution required around 150 Base Rules. With the user interface that I reference as "The Matrix", they play together.

The language can be just about anything. The first version was in VBA using Access. This allowed extremely fast prototyping for two times a day meetings with the Subject Matter Experts. Nobody had a playbook. Once the prototype was completed, it was converted into Scalar Functions on SQL Server. The user side (The Matrix) is table driven.

Once completed and turned on, it probably replaced around 100 human hours a week. More important, it can predict work-flow management and raise Quality Assurance to a very high level. Vastly lowering mistakes in the Regulatory industry is priceless. It is difficult to put a number on that.

This is a great introductry article. Readers should feel encouraged to take it to the next level.
QuestionXML Rule Repository Pin
Member 1104775117-Jun-15 9:28
Member 1104775117-Jun-15 9:28 
QuestionVery Interesting Pin
ugo.marchesini16-Jun-15 4:38
professionalugo.marchesini16-Jun-15 4:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.