规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策。接受数据输入,解释业务规则,并根据业务规则做出业务决策。比较常见的业务规则引擎有Drools、VisualRules 和iLog。这里介绍另外一个C#开源工具RulesEngine。下面通过一个例子来他如何使用。
假设一个设备时检测管道压力值的,如果管道压力超过设定值,就立即报警,检测周期假设值1分钟一次,那么如果压力值超过设定值,系统就会每隔一分钟就会产生一个报警,报警数量太多。
如果要求超过设定值了报警,然后在5分钟内不在报警,并且如果5分钟后,压力值仍然超过设定值,但是没有高于设定值的20%,系统不报警,超过20%再报警。
上面的例子,很典型也很常见,如果上面满足不了需求了,还要增加压力的斜率限制,要是总改代码是不是很烦,有了RulesEngine这些问题统统都很easy.
创建工程,使用Nuget添加RulesEngine
添加如下代码
using Newtonsoft.Json;
using RulesEngine.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace RulesEngineTest
{
class Program
{
static async Task Main(string[] args)
{
//模拟用户的输入内容
var inputValue = new InputValue
{
TimeDifference = 300,
CurrentValue = 1.21,
HistoryValue = 1.0
};
//定义规则
var rulesStr = @"[{
""WorkflowName"": ""InputValueWorkflow"",
""Rules"": [
{
""RuleName"": ""CheckTimeDifference"",
""ErrorMessage"": ""间隔时间要大于300秒."",
""ErrorType"": ""Error"",
""RuleExpressionType"": ""LambdaExpression"",
""Expression"": ""TimeDifference > 300""
},
{
""RuleName"": ""CheckValueGradient"",
""ErrorMessage"": ""梯度值要大于20%."",
""ErrorType"": ""Error"",
""RuleExpressionType"": ""LambdaExpression"",
""Expression"": ""((CurrentValue - HistoryValue)/HistoryValue) > 0.2""
}
]
}] ";
//反序列化Json格式规则字符串
var workflowRules = JsonConvert.DeserializeObject<List<WorkflowRules>>(rulesStr);
//初始化规则引擎
var rulesEngine = new RulesEngine.RulesEngine(workflowRules.ToArray());
//使用规则进行判断,并返回结果
List<RuleResultTree> resultList = await rulesEngine.ExecuteAllRulesAsync("InputValueWorkflow", inputValue);
//返回结果并展示
foreach (var item in resultList)
{
Console.WriteLine("验证成功:{0},消息:{1}", item.IsSuccess, item.ExceptionMessage);
}
Console.ReadLine();
}
}
public class InputValue
{
public double CurrentValue { get; set; }
public double HistoryValue { get; set; }
public int TimeDifference { get; set; } //距离上一个报警的时间差(ms)
}
}
运行结果
如果设置TimeDifference = 301
增加梯度效验
{
""RuleName"": ""CheckValueSlope"",
""ErrorMessage"": ""每秒压力变化要超过0.001."",
""ErrorType"": ""Error"",
""RuleExpressionType"": ""LambdaExpression"",
""Expression"": ""((CurrentValue - HistoryValue)/TimeDifference) > 0.001""
}