github地址: microsoft/RulesEngine
这里我由于项目中是framework的,所以我装的framework版本,直接在项目中,打开nuget管理,
搜索RulesEngine安装即可。
先配置Rule Json字符串,比如我这里声明一个test,里面有两个规则,test1,test4,表达式条件分别为:
test1:传入的值中,CODE要为test,同时NAME为test1,2,3的,使用这个规则;
test2:传入的值中,CODE要为test,同时NAME为test4,5的,使用这个规则;
[
{
"WorkflowName": "test",
"Rules": [
{
"RuleName": "test1",
"SuccessEvent": "test1匹配成功!",
"ErrorMessage": "One or more adjust rules failed.",
"ErrorType": "Error",
"RuleExpressionType": "LambdaExpression",
"Expression": "input1.CODE == \"test\" AND ( input1.NAME == \"test1\" OR input1.NAME == \"test2\" OR input2.NAME == \"test3\" )"
},
{
"RuleName": "test4",
"SuccessEvent": "test4匹配成功",
"ErrorMessage": "One or more adjust rules failed.",
"ErrorType": "Error",
"RuleExpressionType": "LambdaExpression",
"Expression": "input1.CODE == \"test\" AND ( input1.NAME == \"test4\" OR input1.NAME == \"test5\" )"
}
]
}
]
将这个json值存入数据库表Rules中,id为1,Rule为值;
后端代码,:
var db = DBHelper.DB2; //DB访问
var rules = db.Queryable<Rules>().Where(x => x.ID == 1).First(); //找到id为1的rule json
var bre = new RulesEngine.RulesEngine(JsonConvert.DeserializeObject<List<WorkflowRules>>(rules.Rule).ToArray(), null); //声明一个RulesEngine
var testInfo = "{\"CODE\": \"test\",\"NAME\": \"test4\"}"; //声明传入参数变量,实际使用中的数据
string result = ""; //结果
List<RuleResultTree> resultList = bre.ExecuteRule("test", JsonConvert.DeserializeObject<ExpandoObject>(testInfo, new ExpandoObjectConverter())); //执行规则,这里传入实际值,且第一个参数"test"是json中的WorkflowName
resultList.OnSuccess((eventValue) =>
{
result = $"{eventValue}";
});
resultList.OnFail(() =>
{
result = "False!";
});
Console.WriteLine("匹配结果:" + result);
这样就可以运行起来了。
实际使用过程中,肯定不会像上面这样这么简单,不过上面已经可以覆盖多数范围了,我们实际使用中,数据一般都是Entitiy,那么这时候,RuleEngine支持localParams
使用方式基本类似:
声明rule json:
[
{
"WorkflowName": "test",
"Rules": [
{
"RuleName": "test1",
"SuccessEvent": "true",
"ErrorMessage": "One or more adjust rules failed.",
"ErrorType": "Error",
"localParams": [
{
"Name": "model1",
"Expression": "input1model.Where(CODE.Equals(\"test\", StringComparison.InvariantCultureIgnoreCase))"
}
],
"RuleExpressionType": "LambdaExpression",
"Expression": "model1.Any() AND ( inputmodel2.CODE == \"11\" OR inputmodel2.CODE == \"22\" OR inputmodel2.CODE == \"33\" )"
}
]
}
]
如我上面的rule,若是要使用Where条件,这里需要传入Entitiy,而不能传入json字符串,这个传入json字符串虽然也有code字段,但是不认。
后端代码:
var db = DBHelper.DB2;
var rules = db.Queryable<Rules>().Where(x => x.ID == 3).First();
var mpiylist = db.Queryable<MD_PRODUCT_INFO_Y>().ToList();
var macList = db.Queryable<MD_ALL_CHAPTER_INFO>().ToList();
var bre = new RulesEngine.RulesEngine(JsonConvert.DeserializeObject<List<WorkflowRules>>(rules.Rule).ToArray(), null);
foreach (var item in mpiylist)
{
var ruleParams = new List<RuleParameter>();
ruleParams.Add(new RuleParameter("input1model", Utils.GetTypedObject(macList))); \\inputmodel1 这个要跟rule里对应起来,名字可以自定义
ruleParams.Add(new RuleParameter("inputmodel2", Utils.GetTypedObject(item))); \\这里要这样传入,不能先将entity json化后再传入,这样rule中的Where条件不起作用,
List<RuleResultTree> resultList = bre.ExecuteRule("test", ruleParams?.ToArray());
string result = "False";
resultList.OnSuccess((eventValue) =>
{
result = $"{eventValue}";
});
resultList.OnFail(() =>
{
result = "False!";
});
Console.WriteLine("匹配结果:" + result);
}
基本使用方式就是这样,目前的已经可以满足我的需求了,未再深入。