DEV Community

Cover image for Understanding MS Rules Engine — Nested Rules — Part 5
Vamsi Dogiparthi
Vamsi Dogiparthi

Posted on • Originally published at Medium

Understanding MS Rules Engine — Nested Rules — Part 5

Nested Rules Json

Hi Buddy! Welcome back to the part 5 of the MS Rules Engine series. In this article we will be concentrating on how to build simple nested rules with different Operators OR, AND How to parse the nested rules output actions from the ResultTree. So, without any further delay. Let's get started!! 😁

Configuring Simple Nested Rules Without Actions

In this section, few important pieces of Nested Rules configurations, syntaxes before we dig deep into step-by-step implementation.

Syntax:

In order to define the Nested Rules, we need to follow below syntax.

[
  {
    "WorkflowName": "{NameOfWorkflow",
    "Rules": [ // Parent Rules Array
      {
        "RuleName": "{Rule1Name}",
        "RuleExpressionType": "LambdaExpression",
        "Operator": "Or", // AND or OR
        "Rules" : [ // Nested Rules Array
          {
            "RuleName": "{NestRule2Name}",            
            "RuleExpressionType": "LambdaExpression",
            "Expression": "{Expression}",
          },
          {
            "RuleName": "{NestRule2Name}",           
            "RuleExpressionType": "LambdaExpression",          
            "Expression": "{Expression}",
          }
        ]
      }
    ]
  }
]
Enter fullscreen mode Exit fullscreen mode

Operators:

When we included Nested Rules, one important thing is to note that we need to define the Logical Operator which identifies how the end result of all the Nested Rules should be interpreted. The possible values are below.

  • AND - This represents Logical AND which means to get a true value. You need all the nested rules to be true. If not, it will return false.
  • OR - This represents Logical OR which means to get a true value. You need at least one the nested rules to be true. If not, it will return false.
  • AndElse - This is a synonym for AND. So, the functionality is same.
  • OrElse - This is a synonym for OR. So, the functionality is same.
{  
   "enum": [
            "And",
            "AndAlso",
            "Or",
            "OrElse"
            ]
}
Enter fullscreen mode Exit fullscreen mode

ReSettings:

To configure the nested rules properly and also change its behavior of execution. It's necessary to know one of the rule settings NestedRuleExecutionMode. Which changes the behavior of the rule execution. Possible values are

  • All - Executes all the nested rules regardless of whether the result will affect the overall result. Ex: OR Operator is used to terminate the rule execution when first true value is found. But with All setting regardless of its default behavior all the rules are executed
  • Performance - Executes only the rules which might affect the overall outcome. Ex: When OR Operator is used to terminate the rule execution when first true value is found. With this performance setting it will terminate when it finds the first true value.

Awesome, we just went through some important pieces of configurations which we will be using in the rest of the article to implement the Nested Rules. So, without further delay let's start the implementation part with Use Case Statement, followed by step-by-step implementation.

Use Case:

To demonstrate this functionality, let's take a use case in arcade business where we have to check the inventory of certain genre games belonging to a Platform by Gaming Studio.

When the inventory falls below a threshold for a certain set of games by platform, genre and gaming studio. We want to consider that the rule is a success.

In this article we will try to create one nested rule for Gaming Studio Microsoft and Sony.

Step by Step Implementation:

  • Download the base code from Github Repo.
  • Add a class named RestockingChainNestedRulesExample.cs into your project root folder.
  • Add a new JSON rule named RestockingChainNestedRules.json to your RulesFiles folder.
  • Add below content to the above created Json file.
[
  {
    "WorkflowName": "RestockingChainNestedRules",
    "Rules": [
      {
        "RuleName": "ActionPlaystationGameRestock1",
        "ErrorMessage": "The action game stocks for the playstation are low. Restock by 5 units",
        "ErrorType": "Error",
        "SuccessEvent": "5",
        "RuleExpressionType": "LambdaExpression",
        "Operator": "Or",
        "Rules" : [
          {
            "RuleName": "ActionPlaystationGameRestock1_sony",
            "ErrorMessage": "The action game stocks for the playstation are low. Restock by 5 units",
            "ErrorType": "Error",
            "RuleExpressionType": "LambdaExpression",
            "Expression": "input1.Where(x => x.Genre == \"Action\" AND x.Platform == \"PlayStation\" AND x.GamingStudio == \"Sony\").Sum(x => x.Quantity) < 5",
          },
          {
            "RuleName": "ActionPlaystationGameRestock1_nonsony",
            "ErrorMessage": "The action game stocks for the playstation are low. Restock by 10 units",
            "ErrorType": "Error",
            "RuleExpressionType": "LambdaExpression",          
            "Expression": "input1.Where(x => x.Genre == \"Action\" AND x.Platform == \"PlayStation\" AND x.GamingStudio == \"Microsoft\").Sum(x => x.Quantity) < 5",
          }
        ]
      }
    ]
  }
]
Enter fullscreen mode Exit fullscreen mode
  • Modify the Game.cs model class under model's folder to include a new property called Quantity of type integer as show below.
namespace MsRulesEngine.Models;
public class Game {
    public string Title { get; set; } = string.Empty;
    public string Genre { get; set; } = string.Empty;
    public long Id { get; set; }
    public string Platform { get; set; } = string.Empty;    
    public string GamingStudio { get; set; } = string.Empty;
    public decimal Price { get; set; }
    public int Quantity { get; set; }
}
Enter fullscreen mode Exit fullscreen mode
  • Lets now add some code to our new RestockingChainNestedRulesExample.cs class file as shown below.
using RE = RulesEngine;

namespace MsRulesEngine;
public class RestockingChainNestedRulesExample
{
    public static async Task Run()
    {

        string filePath = Path.Combine(Environment.CurrentDirectory, "RulesFiles", "RestockingChainNestedRules.json");
        Console.WriteLine(filePath);
        string jsonString = File.ReadAllText(filePath);

        var workflows = JsonSerializer.Deserialize<Workflow[]>(jsonString);

        var gamesInventory = new List<Game>
        {
            new() {
                Title = "Halo",
                Genre = "Action",
                Id = 1,
                Platform = "PlayStation",
                GamingStudio = "Sony",
                Price = 59.99m,
                Quantity = 1
            },
            new() {
                Title = "Yakuza",
                Genre = "Action",
                Id = 2,
                Platform = "PlayStation",
                GamingStudio = "EA",
                Price = 49.99m,
                Quantity = 2
            },
        };

        var ruleParameters = new RuleParameter[] {
        new ("input1", gamesInventory),
      };

        var settings = new ReSettings
        {
            NestedRuleExecutionMode = NestedRuleExecutionMode.Performance
        };

        RE.RulesEngine rulesEngine = new(workflows);

        var resultList = await rulesEngine.ExecuteAllRulesAsync("RestockingChainNestedRules", ruleParameters, settings);

        foreach (var result in resultList)
        {
            Console.WriteLine($"Rule: {result.Rule.RuleName}, Result: {result.IsSuccess}, Message: {result.ExceptionMessage}");
            if (result.ActionResult != null)
            {
                Console.WriteLine($"Action Result: {result.ActionResult.Output}");
            }
        }
    }

}
Enter fullscreen mode Exit fullscreen mode
  • Modify the program.cs as shown below and execute the application.
   using MsRulesEngine;
   await RestockingChainNestedRulesExample.Run();
Enter fullscreen mode Exit fullscreen mode
  • You will observe the below output. It returns the result as true. As game from the Sony fell below the threshold. Output Image

Advantages of Nested Rules:

  • Easy to have different sub expressions for a single parent rule.
  • Define Logical Operators between nested expressions in a more scalable and manageable way.
  • Breaking down the complex expressions into sub expressions.
  • Easy to change individual expressions on fly.

Conclusion:

In our day-to-day business, we come across many scenarios where we want to perform nested rule evaluations which we usually implement with next if else blocks. But with the Nested Rules, we can dynamically inject them to the parent Rule without cluttered and hardcoded if else blocks. Which hard to understand and change

Hope this article will help you understand the use of Nest Rules and provide you guidance to use it for your needs.

To access my source code. Please go to my GitHub Link. In my next article
I will be explaining how to create some Nested Rules with Actions and how to parse those actions. So, follow me to get notification when it is available.

To get more articles like this, please follow me to get notification when they are available.

Until then see ya soon! 😁

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.