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