C# RulesEngine 规则引擎:从入门到看懵( 二 )

在 RulesEngine中 , 有两种方法定义这些 Workflow 和 Rule , 一种是使用代码,一种是 JSON,官方是推荐使用 JSON 的,因为 JSON 可以动态生成,可以实现真正的动态 。
下面我们来看看如何使用 JSON 和代码,分别定义if(Authenticated == true && Age > 18) 这个验证过程 。
JSON 定义:
[{"WorkflowName": "Test","Rules": [{"RuleName": "CheckAuthenticated","Expression": "Authenticated == true"},{"RuleName": "CheckAge","Expression": "Age >= 18"}]}]var rulesStr = "[{... ...}]" // JSONvar workflows = JsonConvert.DeserializeObject<List<Workflow>>(rulesStr);C# 代码:
var workflows = new List<Workflow>();List<Rule> rules = new List<Rule>();Workflow exampleWorkflow = new Workflow();exampleWorkflow.WorkflowName = "Test";exampleWorkflow.Rules = rules;workflows.Add(exampleWorkflow);Rule authRule = new Rule();authRule.RuleName = "CheckAuthenticated";authRule.Expression = "Authenticated == true";rules.Add(authRule);Rule ageRule = new Rule();ageRule.RuleName = "CheckAuthenticated";ageRule.Expression = "Authenticated == true";rules.Add(ageRule);两种方式都是一样的,每个 Workflow 下有多个 Rule,可以定义多个 Workflow 。
当前我们有两个地方要了解:
"RuleName": "CheckAuthenticated","Expression": "Authenticated == true"RuleName:规则名称;
Expression: 真实的代码,必须是符合 C# 语法的代码;
定义好 Workflow 和 Rule 后,我们需要生成规则引擎,直接 new RulesEngine.RulesEngine() 即可:
var bre = new RulesEngine.RulesEngine(workflows.ToArray());

生成引擎是需要一些时间的 。
生成引擎后,我们通过名称指定调用一个 Workflow,并获取每个 Rule 的验证结果:
List<RuleResultTree> resultList = await bre.ExecuteAllRulesAsync("Test", new Buyer{Id = 666,Age = 17,Authenticated = false});完整代码示例如下:
static async Task Main(){// 定义var rulesStr = ... ...// JSON// 生成 Workflow[ Rule[] ]var workflows = JsonConvert.DeserializeObject<List<Workflow>>(rulesStr)!;var bre = new RulesEngine.RulesEngine(workflows.ToArray());// 调用指定的 Workflow,并传递参数,获取每个 Rule 的处理结果List<RuleResultTree> resultList = await bre.ExecuteAllRulesAsync("Test", new Buyer{Id = 666,Age = 17,Authenticated = false});// 打印输出foreach (var item in resultList){Console.WriteLine("规则名称:{0},验证结果:{1}", item.Rule.RuleName, item.IsSuccess);}}
C# RulesEngine 规则引擎:从入门到看懵

文章插图
多参数如果商品需要 VIP 才能购买呢?
这里我们再定义一个模型类 , 表示一个用户是否为 VIP 。
public class VIP{public int Id { get; set; }public bool IsVIP { get; set; }}那么这个时候就需要处理两个模型类了 , 为了能够在 Rule 中使用所有的模型类,我们需要为每个模型类定义 RuleParameter
var rp1 = new RuleParameter("buyer", new Buyer{Id = 666,Age = 20,Authenticated = true});var rp2 = new RuleParameter("vip", new VIP{Id = 666,IsVIP = false});
相当于表达式树:
ParameterExpression rp1 = Expression.Parameter(typeof(Buyer), "buyer");ParameterExpression rp2 = Expression.Parameter(typeof(VIP), "vip");可以参考笔者的表达式树系列文章:https://ex.whuanle.cn/
然后重新设计 JSON , 增加一个 Rule:
[{ "WorkflowName": "Test", "Rules": [{"RuleName": "CheckAuthenticated","Expression": "buyer.Authenticated == true"},{"RuleName": "CheckAge","Expression": "buyer.Age >= 18"},{"RuleName": "CheckVIP","Expression": "vip.IsVIP == true"} ]}]然后执行此 Workflow:
List<RuleResultTree> resultList = await bre.ExecuteAllRulesAsync("Test", rp1, rp2);
C# RulesEngine 规则引擎:从入门到看懵

文章插图
完整代码:
static async Task Main(){// 定义var rulesStr = ... ... // JSONvar workflows = JsonConvert.DeserializeObject<List<Workflow>>(rulesStr)!;var bre = new RulesEngine.RulesEngine(workflows.ToArray());var rp1 = new RuleParameter("buyer", new Buyer{Id = 666,Age = 20,Authenticated = true});var rp2 = new RuleParameter("vip", new VIP{Id = 666,IsVIP = false});List<RuleResultTree> resultList = await bre.ExecuteAllRulesAsync("Test", rp1, rp2);foreach (var item in resultList){Console.WriteLine("规则名称:{0},验证结果:{1}", item.Rule.RuleName, item.IsSuccess);}}全局参数、本地参数全局参数在 Workflow 中可以定义全局参数,参数对 Workflow 内的所有 Rule 起效,所有 Rule 都可以使用它 。

推荐阅读