Hi Buddy! Welcome back to the part 3 of the MS Rules Engine series. In this article we will be concentrating on how to use different in-built post rule actions to return different action outputs or to create a chain of rule executions.
In this article we will learn how to configure one of the two different types of built-in post rule action execution that are shipped with MSRules Engine. So, lets dive into the next steps.
Configuring OuputExpression built-in action
In this section, let's explore how to configure OutputExpression to execute lambda expressions to produce different outputs on success and failure of a rule.
Use Case:
To demonstrate this functionality, let's take a use case in our arcade business where we have to check the inventory of certain genre games belonging to a platform.
When the inventory falls below a threshold, we want to calculate the quantity of games that we need to reorder for the genre and platform in question.
Step by Step Implementation:
- Download the base code from Github Repo.
- Add a class named
RestockingRulesExample.cs
into your project root folder. - Add a new JSON rule named
RestockingRules.json
to yourRulesFiles
folder. - Add below content to the above created json file.
[
{
"WorkflowName": "RestockingRules",
"Rules": [
{
"RuleName": "ActionPlaysationGameRestock1",
"ErrorMessage": "The action game stocks for the playstation are low. Restock by 5 units",
"ErrorType": "Error",
"SuccessEvent": "5",
"RuleExpressionType": "LambdaExpression",
"Expression": "input1.Where(x => x.Genre == \"Action\" AND x.Platform == \"PlayStation\").Sum(x => x.Quantity) < 5",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "input1.Where(x => x.Genre == \"Action\" AND x.Platform == \"PlayStation\").Sum(x => x.Quantity) * 5"
}
}
}
},
{
"RuleName": "RPGXboxGameRestock1",
"ErrorMessage": "The RPG game stocks for the Xbox are low. Restock by 10 units",
"ErrorType": "Error",
"RuleExpressionType": "LambdaExpression",
"SuccessEvent": "10",
"Expression": "input1.Where(x => x.Genre == \"RPG\" AND x.Platform == \"Xbox\").Sum(x => x.Quantity) < 10",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "input1.Where(x => x.Genre == \"RPG\" AND x.Platform == \"Xbox\").Sum(x => x.Quantity) * 10"
}
}
}
}
]
}
]
- 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; }
}
- Lets now add some code to our new
RestockingRulesExample.cs
class file as shown below.
using RE = RulesEngine;
namespace MsRulesEngine;
public class RestockingRulesExample
{
public static async Task Run()
{
string filePath = Path.Combine(Environment.CurrentDirectory, "RulesFiles", "RestockingRules.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 = 2
},
new() {
Title = "Yakuza",
Genre = "RPG",
Id = 2,
Platform = "Xbox",
GamingStudio = "EA",
Price = 49.99m,
Quantity = 5
},
new() {
Title = "Persona 5",
Genre = "Sports",
Id = 3,
Platform = "Xbox",
GamingStudio = "EA",
Price = 49.99m,
Quantity = 6
}
};
RE.RulesEngine rulesEngine = new(workflows);
var resultList = await rulesEngine.ExecuteAllRulesAsync("RestockingRules", gamesInventory);
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}");
}
}
}
}
- Modify the
program.cs
as shown below and execute the application.
// See https://aka.ms/new-console-template for more information
using MsRulesEngine;
//await SimpleDiscountRules.Run();
await RestockingRulesExample.Run();
- You will observe the below output. It calculates 10 as restock quantity for PlayStation Action games and 50 for Xbox RPG games.
Advantages of OutputExpression:
- Calculation expression can be configured on runtime using json file.
- Can use complex lambda expressions in the json file to calculate the output.
- Can define different action results on success and failure of a rule or set of rules.
- No code change needed to change the calculation expression.
- Less turnaround time
Conclusion:
In our day-to-day business, we come across many scenarios where we want to perform various calculations or return different outputs out of a rule execution based on its status such as OnSuccess and OnFailure.
This dynamic behavior helps us take appropriate follow up actions. Also, because of its dynamic nature we can easily change these calculations as our business changes.
Hope this article will help you understand the use of built-in OutputExpression Action and provide you guidance to use it for your needs.
To access my source code. Please go to my Github Link.
If you are learning from articles and want to stay tuned of my future articles, please like this article and follow me!
Until then see ya soon! 😁
Top comments (0)