Using Output expressions with the Microsoft Rules engine

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

Leave a Reply

Your email address will not be published. Required fields are marked *