在 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);}}

文章插图
多参数如果商品需要 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});
相当于表达式树:然后重新设计 JSON , 增加一个 Rule:
ParameterExpression rp1 = Expression.Parameter(typeof(Buyer), "buyer");ParameterExpression rp2 = Expression.Parameter(typeof(VIP), "vip");
可以参考笔者的表达式树系列文章:https://ex.whuanle.cn/
[{ "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);

文章插图
完整代码:
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 都可以使用它 。
推荐阅读
- maven 重复依赖不同版本 选择规则
- 我的世界如何附魔(我的世界附魔叠加规则)
- 即兴小探华为开源行业领先大数据虚拟化引擎openLooKeng
- 德州扑克的规则是怎样的(德州扑克口诀顺口溜)
- Silky微服务框架之服务引擎
- 红心大战玩法(网上红心大战规则)
- sentinel的四种流控规则介绍
- 红心大战怎么玩(红心大战的玩法和规则)
- 红心大战规则详细讲解(网上红心大战规则)
- MasaFramework -- 缓存入门与规则配置