首页 > 其他分享 >.NET的RulesEngine(规则引擎)使用

.NET的RulesEngine(规则引擎)使用

时间:2023-03-10 11:46:57浏览次数:51  
标签:string var 引擎 规则 RulesEngine NET Expression 2.4

本文目录
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种:AndAndAlsoOrOrElse
ErrorMessage string 错误信息。用于返回的信息
ErrorType enum 错误类型。共有两种:WarningError
SuccessEvent string 完成事件,默认为规则名称
Rules Rules 规则数组,也就说可以嵌套

2.2.3 第三部分参数说明

第三部分参数在文档中称之为Leaf Rule,意思就是最小的规则。也就是具体规则内容。

参数名称类型说明必须
RuleName string 规则的名称
Expression string 表单式,具体的规则内容
RuleExpressionType enum 虽然是枚举类型,但目前只有一种,只能填写LambdaExpression
ErrorMessage string 提示的错误信息
ErrorType enum 错误类型。共有两种:WarningError
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

相关文章

  • 国外SEO升级攻略:如何应对搜索引擎算法变化?
    搜索引擎优化(SEO)是一个动态的领域,搜索引擎的算法经常会发生变化,这意味着SEO专业人员需要保持更新的技术知识和策略,以适应变化并提高网站的排名。以下是一些应对搜索引擎算法......
  • netcore 上传文件
    一般上传文件可以用formdata的文件格式将你要上传的文件和其他参数放在一个类里面例如:publicclassuploadItemFile{publicintid{get;set;}publicF......
  • kaldi在linux上编译,Ubuntu 12.04下编译安装Kaldi https://blog.csdn.net/we
    因为同事工作需要kaldi,所以安装过程有点麻烦。在此记录一下折腾的过程。OS:Ubuntu 12.04(amd64)kaldi的下载地址 http://svn.code.sf.net/p/kaldi/code/ 我这里下......
  • ASP.NET Core - 配置系统之配置添加
    2.配置添加配置系统可以读取到配置文件中的信息,那必然有某个地方可以将配置文件添加到配置系统中。之前的文章中讲到ASP.NETCore入口文件中,builder(WebApplicationBui......
  • 如何在 Net6.0 中对 WebAPI 进行 JWT 认证和授权
    一、简介我们做微服务开发,或者说做分布式开发,有一项技术我们是避不开的,那就是WebAPI,在Net6.0中,有两类WebAPI,一类是极简WebAPI,它砍掉了很多冗余的东西,更纯粹的是......
  • ASP.NET Core - 配置系统之配置读取
    一个应用要运行起来,往往需要读取很多的预设好的配置信息,根据约定好的信息或方式执行一定的行为。配置的本质就是软件运行的参数,在一个软件实现中需要的参数非常多,如果我们......
  • 使用ControlNet 控制 Stable Diffusion
    本文将要介绍整合HuggingFace的diffusers包和ControlNet调节生成文本到图像,可以更好地控制文本到图像的生成ControlNet是一种通过添加额外条件来控制扩散模型的神经网络......
  • .netcore全局异常处理
    一、背景某天,应用程序进程无缘无故退出,也就是我们通常说的崩溃。通常情况下,windows事件会记录一条消息。但是有时候,我们发现这样的信息,对于查找问题,还是远远不够的,因为它......
  • .NET静态代码织入——肉夹馍(Rougamo) 发布1.4.0
    肉夹馍(https://github.com/inversionhourglass/Rougamo)通过静态代码织入方式实现AOP的组件,其主要特点是在编译时完成AOP代码织入,相比动态代理可以减少应用启动的初始化时......
  • API发布与部署-- .NET WebAPI 篇
    API发布-- .NET  WebAPI 篇1:准备工作:设置数据库链接字符串,打开一个正常的项目:首先注意所有的appsettings.json文件,包括生产环境配置子文件,注意里面的链......