Rule Engine
Getting Started
A fast and reliable .NET Rules Engine with extensive Dynamic expression support - microsoft/RulesEngine
https://github.com/microsoft/RulesEngine/wiki/Getting-Started
- To install this library, please download the latest version of NuGet Package from nuget.org and refer it into your project.
- Initiate the instance of Rules Engine as mentioned in Initiating the Rules Engine.
- Once done, the rules can be executed using any of the overloaded methods as explained in IRulesEngine section. It returns the list of RuleResultTree which can be used in any way the user wants to.
- The success or failure events can be defined as explained in the Success/Failure section.
- Based on the rules and input the success or failure event can be triggered.
Objects
Rules
A lambda expression that can be executed.
Rules Schema
The schema for storing those rules.
[
{
"WorkflowName": "Discount",
"Rules": [
{
"RuleName": "GiveDiscount10",
"SuccessEvent": "10",
"ErrorMessage": "One or more adjust rules failed.",
"ErrorType": "Error",
"RuleExpressionType": "LambdaExpression",
"Expression": "input1.country == \"india\" AND input1.loyalityFactor <= 2 AND input1.totalPurchasesToDate >= 5000 AND input2.totalOrders > 2 AND input3.noOfVisitsPerMonth > 2"
},
]
}
]ReSettings
Allows you to use custom functions in the rule.
First a class to hold custom functions.
using System;
using System.Linq;
namespace RE.HelperFunctions
{
public static class Utils
{
public static bool CheckContains(string check, string valList)
{
if (String.IsNullOrEmpty(check) || String.IsNullOrEmpty(valList))
return false;
var list = valList.Split(',').ToList();
return list.Contains(check);
}
}
}Second use the method in the lambda expression like this.
"Expression": "Utils.CheckContains(input1.country, \"india,usa,canada,France\") == true"Third register the rule engine class with the custom types.
var reSettingsWithCustomTypes = new ReSettings { CustomTypes = new Type[] { typeof(Utils) } };
new RulesEngine.RulesEngine(workflowRules.ToArray(), null, reSettingsWithCustomTypes);RuleParameter
In your expressions you have to get the inputs by names like input1.country. But you might want to use better names like transaction.country. The parameter class allows you to change the name of the inputs.
var ruleParameter = new RuleParameter(
"transaction",
input);LocalParams
Allows you to break a single large expression down into smaller expressions.
{
"name": "allow_access_if_all_mandatory_trainings_are_done_or_access_isSecure",
"errorMessage": "Please complete all your training(s) to get access to this content or access it from a secure domain/location.",
"errorType": "Error",
"localParams": [
{
"name": "completedSecurityTrainings",
"expression": "MasterSecurityComplainceTrainings.Where(Status.Equals(\"Completed\", StringComparison.InvariantCultureIgnoreCase))"
},
{
"name": "completedProjectTrainings",
"expression": "MasterProjectComplainceTrainings.Where(Status.Equals(\"Completed\", StringComparison.InvariantCultureIgnoreCase))"
},
{
"name": "isRequestAccessSecured",
"expression": "UserRequestDetails.Location.Country == \"India\" ? ((UserRequestDetails.Location.City == \"Bangalore\" && UserRequestDetails.Domain=\"xxxx\")? true : false):false"
}
],
"expression": "(completedSecurityTrainings.Any() && completedProjectTrainings.Any()) || isRequestAccessSecured "
}RuleResultTree
Output of the rule engine. It holds the following.
Rule- that is being referred to
IsSuccess- Boolean value rule evaluated to
ChildResults- if rule has child rules, this holds their results
Input- the input that was check on when verifying the object. If multiple inputs, this will be first.
IRuleEngine
Interface for executing rules.
List<RuleResultTree> ExecuteRule(string workflowName, IEnumerable<dynamic> input, object[] otherInputs);
List<RuleResultTree> ExecuteRule(string workflowName, object[] inputs);
List<RuleResultTree> ExecuteRule(string workflowName, object input);
List<RuleResultTree> ExecuteRule(string workflowName, RuleParameter[] ruleParams);workflowName- name of workflow
input- list of dynamic inputs
otherInputs- this is a strange param, this essentially allows you to add extra inputs, in the past input only allowed you to pass a single object. So this allows you to add more. No need to use it.
ruleParams- as mentioned before, helps define names for inputs
Init RuleEngine
public RulesEngine(string[] jsonConfig,ReSettings reSettings = null)
public RulesEngine(WorkflowRules[] workflowRules, ReSettings reSettings = null)jsonConfig- config defined in
reSettings- custom methods as defined in
workflowRules- list of objects that defines the workflow as defined in
Events
OnSuccess
Called when one or more rules passed.
List<RuleResultTree> resultList = bre.ExecuteRule("Discount", inputs);
resultList.OnSuccess((eventName) =>
{
discountOffered = $"Discount offered is {eventName} % over MRP.";
});OnFail
Called when all rules failed.
List<RuleResultTree> resultList = bre.ExecuteRule("Discount", inputs);
resultList.OnFail(() =>
{
discountOffered = "The user is not eligible for any discount.";
});