The Microsoft Rules engine is a powerful tool to isolate business logic from an application and supports output parameters. Suppose we have a requirement to detect duplicate items in a string, and then output these items. The rules-engine itself works on expressions who always evaluate to true or false, but you can also register an ‘OnSuccess’-event to be executed when an expression evaluates to true. Inside this, you can create an expression to return the information you need.
So consider the following list of fruits :
var stringList = new List<string> { "apple", "banana", "apple", "orange", "peach", "banana" };
the result then should be “apple,banana”. This can be accomplished by the following workflow:
[ { "WorkflowName" : "FindFrequentFruitsWorkflow", "Rules" : [ { "RuleName" : "CountFruit", "RuleExpressionType" : "LambdaExpression", "Expression" : "input1.GroupBy(i => i).Any(g => g.Count() > 1)", "Actions" : { "OnSuccess" : { "Name" : "OutputExpression", "Context" : { "Expression" : " string.Join( \",\", input1.GroupBy(s => s).Where(g => g.Count() > 1).Select(g => g.Key).ToList().ToArray())" } } } } ] } ]
Code to execute this workflow looks like this:
string currentDirectory = Directory.GetCurrentDirectory(); string folder = Directory.GetParent(Directory.GetParent(Directory.GetParent(currentDirectory).FullName).FullName).FullName; var files = Directory.GetFiles(folder, "count_multiple_occurrences_output.json", SearchOption.AllDirectories); var fileData = File.ReadAllText(files[0]); var workflows = JsonConvert.DeserializeObject<List<Workflow>>(fileData); var stringList = new List<string> { "apple", "banana", "apple", "orange", "peach", "banana" }; string workflowName = "FindFrequentFruitsWorkflow"; List<RuleResultTree> resultList = new RulesEngine.RulesEngine(workflows.ToArray()).ExecuteAllRulesAsync(workflowName, stringList).Result; var tasks = resultList.ToList(); int c = resultList.Where(x => x.IsSuccess == true).Count(); System.Console.WriteLine($"{c} rules succeeded"); foreach (var task in tasks) { System.Console.WriteLine($"Rule=[{task.Rule}] name=[{task.Rule.RuleName}], IsSuccess=[{task.IsSuccess}]"); if (task.IsSuccess == false) { if (task.ExceptionMessage != task.Rule.ErrorMessage) { System.Console.WriteLine($"Invalid rule:[{task.ExceptionMessage}]"); continue; } System.Console.WriteLine($"ErrorMessage=[{task.Rule.ErrorMessage}]"); continue; } System.Console.WriteLine($"{task.Rule.SuccessEvent}"); System.Console.WriteLine(task.Rule.Actions.ToString()); string name = task.Rule.Actions.OnSuccess.Name; System.Console.WriteLine($"name=[{name}], value=[{task.ActionResult.Output}]"); foreach (var item in task.Rule.Actions.OnSuccess.Context) { System.Console.WriteLine(item.ToString()); } }
Compiling and executing this produces the following output:
A working example can be found over here