本文目录
1、背景说明
1.1 规则引擎的使用场景
1.2 demo的代码说明
2、演示
2.1 入门demo演示
2.1.1 代码展示
2.1.2 代码下载
2.2 规则参数说明
2.2.1 第一部分参数说明
2.2.2 第二部分参数说明
2.2.3 第三部分参数说明
2.3 在Expression使用自定义判断
2.3.1 先编写业务逻辑判断方法
2.3.2 通过ReSettings进行增加自定义类型
2.3.2 修改具体规则
2.3.3 将自定义类型进行注册
2.3.4 代码下载
2.4 其他参数说明
2.4.1 RuleParameter(规则参数)
2.4.2 LocalParams(本地变量)
2.4.2.1 代码下载
2.4.3 GlobalParams(全局变量)
2.4.3 返回结果
2.4.3.1 方法1
2.4.3.2 方法2
2.5 后续学习
2.6 参考资料
1、背景说明
1.1 规则引擎的使用场景
RulesEngine是Microsoft推出的一个规则引擎项目,用于系统中抽象出的业务逻辑/规则/策略。在医疗行业中经常涉及的功能就是知识库或CDSS,这个基本上就是各种各样的规则集合及提示。例如:两个药品之间会有配伍禁忌、相互作用,因此不能一起配液或同时使用;某药品的给药频率为一天一次(QD),不可为一天三次(TID)、一天四次(QID)等。而这种场合的特点就是输入信息基本不变,规则经常变(常常是增加)。现阶段增加意味着增加代码,发布版本。因此普通企业/软件的这种需求,特别适合规则引擎。
偶然在网上看到规则引擎,当天就研究了下,真的是太好用了!所以总结一下
1.2 demo的代码说明
我用的环境:win10企业版、VS2019社区版,.NET Framework 4.7.2,然后新建控制台程序
2、演示
首先从NuGet上下载并安装RulesEngine。如图所示
2.1 入门demo演示
2.1.1 代码展示
控制台代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; using RulesEngine.Models; namespace REDemo2 { class Program { static async Task Main(string[] args) { //模拟用户的输入内容 var userInput = new UserInput { IdNo = null, Age = 18 }; //定义规则 var rulesStr = @"[{ ""WorkflowName"": ""UserInputWorkflow"", ""Rules"": [ { ""RuleName"": ""CheckAge"", ""ErrorMessage"": ""年龄必须大于18岁."", ""ErrorType"": ""Error"", ""RuleExpressionType"": ""LambdaExpression"", ""Expression"": ""Age > 18"" }, { ""RuleName"": ""CheckIDNoIsEmpty"", ""ErrorMessage"": ""身份证号不可以为空."", ""ErrorType"": ""Error"", ""RuleExpressionType"": ""LambdaExpression"", ""Expression"": ""IdNo != null"" } ] }] "; //反序列化Json格式规则字符串 var workflowRules = JsonConvert.DeserializeObject<List<WorkflowRules>>(rulesStr); //初始化规则引擎 var rulesEngine = new RulesEngine.RulesEngine(workflowRules.ToArray()); //使用规则进行判断,并返回结果 List<RuleResultTree> resultList = await rulesEngine.ExecuteAllRulesAsync("UserInputWorkflow", userInput); //返回结果并展示 foreach (var item in resultList) { Console.WriteLine("验证成功:{0},消息:{1}", item.IsSuccess, item.ExceptionMessage); } Console.ReadLine(); } } public class UserInput { public string IdNo { get; set; } public int Age { get; set; } } }
代码的规则,只是简单的验证年龄必须大于18岁及身份证号不能为空。
运行以上代码,展示的结果如下:
可以通过以上的入门demo展示规则引擎的使用。
2.1.2 代码下载
样例代码下载。代码下载 提取码:NHZL
2.2 规则参数说明
先拿一个完整的样例说一下规则,如下图所示
整个规则分为如上图的三部分,这三者又是嵌套的关系。其中1和3是必须的,2可有可无。若没有2,则全部按默认处理。这三部分的定义如下
2.2.1 第一部分参数说明
整个规则分为如上图的三部分,这三者又是嵌套的关系。其中1和3是必须的,2可有可无。若没有2,则全部按默认处理。这三部分的定义如下
2.2.1 第一部分参数说明
第一部分的参数只有两个。两个都是必须项,具体定义如下
参数名称 | 类型 | 说明 | 必须 |
---|---|---|---|
WorkflowName | string | 定义被规则引擎识别的名称 | 是 |
Rules | array | 具体的规则。规则可以进行多层嵌套 | 是 |
2.2.2 第二部分参数说明
第二部分官方文档中称之为Rule。具体定义如下
参数名称 | 类型 | 说明 | 必须 |
---|---|---|---|
RuleName | string | 规则的名称 | 是 |
Operator | enum | 操作符.用于第3部分多个规则之间的关系。共有4种:And 、AndAlso 、Or 、OrElse |
是 |
ErrorMessage | string | 错误信息。用于返回的信息 | 否 |
ErrorType | enum | 错误类型。共有两种:Warning 、Error |
否 |
SuccessEvent | string | 完成事件,默认为规则名称 | 否 |
Rules | Rules | 规则数组,也就说可以嵌套 | 是 |
2.2.3 第三部分参数说明
第三部分参数在文档中称之为Leaf Rule
,意思就是最小的规则。也就是具体规则内容。
参数名称 | 类型 | 说明 | 必须 |
---|---|---|---|
RuleName | string | 规则的名称 | 是 |
Expression | string | 表单式,具体的规则内容 | 是 |
RuleExpressionType | enum | 虽然是枚举类型,但目前只有一种,只能填写LambdaExpression |
是 |
ErrorMessage | string | 提示的错误信息 | 否 |
ErrorType | enum | 错误类型。共有两种:Warning 、Error |
否 |
SuccessEvent | string | 完成事件,默认为规则名称 | 否 |
以上定义的官方文档:官方文档链接
2.3 在Expression使用自定义判断
上面的例子在第三部分的参数(leaf rule)的Expression中,只能使用系统(system)自带的方法进行逻辑判断。即string自带的方法、int自带的方法。若想使用自定义方法,则需要进行额外的处理。
2.3.1 先编写业务逻辑判断方法
首先先编写业务逻辑判断方法,如下所示
public static class IdCardUtil { //此处使用了C#的方法扩展 public static int GetAgeByIdCard(this string str) { //假设进行了相关处理,得到结果 return 45; } //此处是正常的业务逻辑方法 public static int getAgeByIdCardNo(string str) { return 50; } }
2.3.2 通过ReSettings进行增加自定义类型
然后通过ReSettings增加自定义类型
private static readonly RulesEngine.Models.ReSettings reSettings = new RulesEngine.Models.ReSettings { CustomTypes = new[] { typeof(IdCardUtil) } };
2.3.2 修改具体规则
//定义规则 var rulesStr = @"[{ ""WorkflowName"": ""UserInputWorkflow"", ""Rules"": [ { ""RuleName"": ""CheckNestedSimpleProp"", ""ErrorMessage"": ""年龄必须小于18岁."", ""ErrorType"": ""Error"", ""RuleExpressionType"": ""LambdaExpression"", ""Expression"": ""IdCardUtil.getAgeByIdCardNo(IdNo) < 18"" //这是常用的方法。 ""Expression"": ""IdNo.GetAgeByIdCard() < 18"" // 这个是使用C#自定义扩展方法。 这两句任选一个就可以。 }, { ""RuleName"": ""CheckNestedSimpleProp1"", ""ErrorMessage"": ""身份证号不可以为空."", ""ErrorType"": ""Error"", ""RuleExpressionType"": ""LambdaExpression"", ""Expression"": ""IdNo != null"" } ] }] ";
规则中""Expression"": ""IdCardUtil.getAgeByIdCardNo(IdNo) < 18""和""Expression"": ""IdNo.GetAgeByIdCard() < 18""的效果是一样的,任选一个就OK了
2.3.3 将自定义类型进行注册
将自定义的内容进行注册
var rulesEngine = new RulesEngine.RulesEngine(workflowRules.ToArray(),null,reSettings); //添加reSettings内容
然后就可以正常运行了。
2.3.4 代码下载
源码下载。代码 提取码:NHZL
2.4 其他参数说明
2.4.1 RuleParameter(规则参数)
可以对输入内容可以使用RuleParameter来进行封装具体的参数类型。
//这是原始的输入 var zhenglininfo = new UserInput { IdNo = null, Age = 18 }; //使用RuleParameter进行封装 RulesEngine.Models.RuleParameter ruleParameter = new RulesEngine.Models.RuleParameter("Test", zhenglininfo); ..... //相应的修改 List<RulesEngine.Models.RuleResultTree> resultList = await rulesEngine.ExecuteAllRulesAsync("UserInputWorkflow", ruleParameter);
2.4.2 LocalParams(本地变量)
这个比较重要,这个会将多个条件进行拆分,并分别单独命名,然后使用这些命名进行逻辑判断。例如
var rulesStr = @"[{ ""WorkflowName"": ""UserInputWorkflow"", ""Rules"": [ { ""RuleName"": ""CheckAge"", ""ErrorMessage"": ""年龄必须大于18岁."", ""ErrorType"": ""Error"", ""localParams"": [ { ""Name"": ""model1"", ""Expression"": ""Age!=0"" }, { ""Name"": ""model2"", ""Expression"": ""IdCardUtil.getAgeByIdCardNo(Test.IdNo) < 18"" } ], ""RuleExpressionType"": ""LambdaExpression"", ""Expression"": ""model1 AND model2"" }, { ""RuleName"": ""CheckIDNoIsEmpty"", ""ErrorMessage"": ""身份证号不可以为空."", ""ErrorType"": ""Error"", ""RuleExpressionType"": ""LambdaExpression"", ""Expression"": ""IdNo != null "" } ] }] ";
上面就是本地变量的规则样例,其中model2中,传入了Test.IdNo,这就是用到了2.4.1的RuleParameter。
2.4.2.1 代码下载
LocalParams的代码下载。下载地址 提取码:NHZL
2.4.3 GlobalParams(全局变量)
GlobalParams(全局变量)是定义在workflow层面,并且可以在任何rule中使用。例如:
//Rule.json { "WorkflowName": "workflowWithGlobalParam", "GlobalParams":[ { "Name":"myglobal1", "Expression":"myInput.hello.ToLower()" } ], "Rules":[ { "RuleName": "checkGlobalEqualsHello", "Expression":"myglobal1 == \"hello\"" }, { "RuleName": "checkGlobalEqualsInputHello", "Expression":"myInput.hello.ToLower() == myglobal1" } ] }
全局变量会在所有的rule中使用,下面的语句将返回true
var input = new RuleParameter("myInput",new { hello = "HELLO" }); var resultList = await re.ExecuteAllRulesAsync("workflowWithGlobalParam",rp);
2.4.3 返回结果
执行完成后,需要查看返回结果。有两种方式查看:
2.4.3.1 方法1
//使用规则进行判断,并返回结果 var resultList = await rulesEngine.ExecuteAllRulesAsync("UserInputWorkflow", ruleParameter); foreach (var item in resultList) { Console.WriteLine("验证成功:{0},消息:{1}", item.IsSuccess, item.ExceptionMessage); }
2.4.3.2 方法2
var resultList = rulesEngine.ExecuteAllRulesAsync("UserInputWorkflow", ruleParameter).Result; resultList.OnSuccess((eventName) => { Console.WriteLine("{0}是ok!", eventName); }).OnFail(() => { Console.WriteLine("失败了!"); });
两个方法略有不同
2.5 后续学习
规则引擎主要是System.Linq.Dynamic.Core,下一步继续学习下这块内容
2.6 参考资料
主要参考资料有:
1、官网资料。官网
2、波多尔斯基 的《C#规则引擎RulesEngine》
3、微软MVP精选 | .NET RulesEngine(规则引擎)
————————————————
版权声明:本文为CSDN博主「zlbcdn」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zlbcdn/article/details/116950118
标签:string,var,引擎,规则,RulesEngine,NET,Expression,2.4 From: https://www.cnblogs.com/wl-blog/p/17202834.html