一、设计目标
a)规则引擎语法能够满足分单,计费,WMS策略的配置要求。语法是一致和统一的
b)能够在不修改规则引擎模块的情况下,加入任意一个新的规则;实现上述需求之外的规则配置需求
c)运算速度快
d)有良好的展现效果,能够在售前阶段帮助销售
e)提供良好的调试和诊断手段,便于配置规则
二、基本语法及使用
在讲解以下章节的内容时,我们来模拟OMS中一个真实的分单业务场景:根据订单不同的出发地城市和目的地城市指派不一样的承运商并创建运单,如果目的地城市为北京则在天津进行中转。
首先:在相关类中增加如下代码:
1.把页面表单控件值取出来放到集合中
Dictionary Dictionary
publicvoidGetFormToParames() { parames.Clear(); parames.Add("出发地", this.txtChuFaDi.Text); parames.Add("到达地", this.txtDaoDa.Text); parames.Add("业务类型", this.icbeCategory.Text); parames.Add("总金额", this.txtTotalMoney.Text); parames.Add("重量", this.txtZhongLiang.Text); parames.Add("运费", this.txtMoney.Text);
}
|
1.把组装好的参数调整规则“类型不同折扣不同主规则”进行执行。
//类型不同折扣不同 privatevoidbtnCategory_Click(object sender, EventArgs e) { GetFormToParames(); RuleServiceruleService = (RuleService)CacheManager.Instance.Retrieve("RuleService"); returns = ruleService.Execute(this.UserInfo, "类型不同折扣不同主规则", parames, this.DbHelper, this.UserCenterDbHelper); if (returns != null) { if (returns.ContainsKey("费用") && returns["费用"] != null) { this.txtMoney.Text = returns["费用"].ToString(); } } } |
ruleService.Execute方法传递参数调用“类型不同折扣不同主规则”,并返回费用进行处理。
2.1、调试输出
1. 语法:打印(Object)
2. 说明:该函数用于调试输出,内容会输出到规则日志上。
类型不同折扣主规则:
打印(“执行类型不同折扣主规则”); |
调用执行后,规则日志控制台便会输出"执行类型不同折扣主规则"
2.2、局部变量
1. 语法:int运费=100
2. 说明:
a)文字前增加int符号就表明该变量是一个整型局部变量;
b)局部变量只能在单个规则文件内部使用。不能被外部赋值和读取
c) 类型可以是C#语法中的任意类型。
规则内容如下:
|
调用方法后在日志控制台便会输出:"标识:0"
2.3、运算符
符号 |
样例 |
说明 |
= |
运费=100 |
向变量进行赋值 |
+,-,*,/,% |
运费=100*20+18 |
加,减,乘,除,取余 |
>,<,>=,<=,<>,!= |
如果(运费>100){} |
逻辑运算符 |
() |
(运费>100)且(运费<1000) |
括号;可以无限嵌套 |
且 |
(运费>100)且(运费<1000) |
与运算 |
|
|
|
|
|
|
例:
如果(字符串参数("业务类型") == "零售") { totalMoney = totalMoney * 0.9; }
如果( 字符串参数("业务类型").Equals( "大客户")) { totalMoney = totalMoney * 0.6; } |
2.4、条件语句
1. 语法:如果(条件表达式){语句}
2. 说明:
a)条件表达式为必须(包括小括号),并且肯定是逻辑表达式,而语句体中的语句可以为任意语句,也就是支持语句嵌套。
b)注意只有如果子句,没有或者子句。
主规则中内容如下:
int标识= 0 // 条件语句, 这里表示:如果订单集为空,则抛出一个异常 如果(订单集== 空) { 异常("订单集为空") } 如果(订单集!= 空) { 打印("正常,订单集不为空") } |
2.5、空值
1. 语法:空,可以用:a==空的方式对于空值进行判断
2. 说明:内置全局变量,用于进行空值判断
主规则中内容如下:
int标识= 0 // 空:内置全局变量,用于进行空值判断 如果(参数集== 空) { 异常("订单集为空") } 如果(参数集!= 空) { 打印("正常,订单集不为空") } |
2.6、循环
1. 语法:
每个(局部变量in列表){ 语句 } |
2. 说明:
a)条件表达式为必须(包括小括号),并且肯定是逻辑表达式,而语句体中的语句可以为任意语句,也就是支持语句嵌套。
b)注意:只有如果子句,没有或者子句。
主规则中内容如下:
int标识= 0 如果(订单集== 空) { 异常("订单集为空") } // 对集合进行循环遍历 每个(订单in订单集) { 打印(订单.序号) } |
调用方法后在控制台日志便会输出:订单序号
三、高级语法及使用
3.1、创建对象
1. 语法:new 实体名(),参数:无,返回值:实体类。
2. 说明:下例第8行创建了一个运单对象,对象可以包含很多属性,变量名.属性名,形如:运单.出发地="A"
int标识= 0 如果(订单集== 空) { 异常("订单集为空") } 每个(OrderEntity订单: 订单集) { OrderEntity运单= new OrderEntity() 运单.出发地= 订单.出发地 运单.目的地= 订单.目的地 打印(运单) } |
调用方法时,在控制台便会输出:运单相关信息
3.2、创建列表
1. 语法:创建列表(),参数:无,返回值:结果集
2. 说明:下例列表,用于存放键值对。
Dictionary |
3.3、子规则
分单规则:
int标识= 0; 打印("分章主规则" + 标识); 如果(标识 == 0){ 子规则分单1(); } |
分单子规则:子规则分单1
/* * BaseUserInfo当前用户 * Dictionary * IDbHelperdbHelper //业务数据库 * IDbHelperuserDbHelper//用户中心数据库 * * 取参数值方法:(强转类型)参数集["key"] * * Dictionary * 返回参数方法:返回列表.Add("key",value); */
打印("子规则分单1------------"); string s, m; BaseRuleLogEntity entity = new BaseRuleLogEntity(); entity.Type = "打印"; entity.Description = "哈哈哈"; SNFService.Instance.CreateService
单值查表("费用表","大连","青岛");
返回列表("key",entity ); |
注:可以直接调用我们服务层代码.
同时我们的调用代码如下:
//01.规则调用代码 System.Collections.Generic.Dictionary ruleService = (RuleService)CacheManager.Instance.Retrieve("RuleService"); ruleService.Execute(BaseSystemInfo.UserInfo, "分单主规则", parames, null, null); |
3.4、内置函数
函数 |
参数 |
返回值 |
说明 |
查表 |
参数1:规则表名称,参数2~N:表示查找参考项值,传值顺序跟规则表定义顺序一致 |
结果集 |
用于规则表的查询,$线路集=查表("上架规则表","海信",64) |
单值查表 |
参数1:数据表名;参数2:值参考项;其余:数据表查找参考项;返回:value |
值 |
string feiyong = 单值查表("运费表","费用",参数集["出发地"].ToString(),参数集["到达地"].ToString()); |
多值查表 |
参数1:数据表名;其余:数据表查找参考项; |
结果列表集(key,value) |
List< Dictionary |
最大 |
参数1~N:数值 |
最大数值 |
求最大值,int 最大值=最大(1,0,5,9,10) |
最小 |
参数1~N:数值 |
最大数值 |
求最小值,int 最小值=最小(1,0,5,9,10) |
|
|
|
|
求和 |
参数1:集合 |
数值 |
对集合中元素进行求和 |
四舍五入 |
参数1:值 |
数值 |
|
四舍五入 |
参数1:值,参数2:精度 |
数值 |
|
向上取整 |
数值 |
整型类型 |
向上取整(数量); |
向下取整 |
数值 |
整型 |
向下取整(数量); |
包含元素 |
参数1:集合类型,参数2:任意类型; |
布尔类型 |
|
格式化字符 |
参数1:值 ;参数2:占位符 ;参数3:位数 |
字符串值 |
|
创建列表 |
无参数 |
结果集 |
创建一个集合,Dictionary |
相隔日 |
参数1:源日期,参数2:目标日期 |
天数 |
获得两个日期间相隔天数 |
相隔月 |
参数1:源日期,参数2:目标日期 |
月数 |
获得两个日期间相隔月数 |
现在 |
无 |
日期 |
获取当前日期 |
异常 |
参数1:消息 |
无 |
判断对象是否为空,如果为空则抛出异常,并且控制台输出消息 |
打印 |
参数1:对象 |
无 |
输出到控制台 |
字符串参数 |
key 参数的key |
string |
|
数值参数 |
key 参数的key |
Double |
|
整数参数 |
key 参数的key |
Int32 |
|
3.5、自定义函数-OK
项目中如果需要公用的函数,则可以在项目中的:RuleExtConfig.txt文件中进行扩展使用如下:
double 重量转换(double weight) { return ExtRule.重量转换(weight); } |
我们再修改一下(或新增)RuleExt.cs类,增加:ConvertWeight方法
using System; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text;
namespaceTony.DEMO.Business { publicclassRuleExt { publicdoubleConvertWeight(double weight) { return weight / 1000; } } }
|
同时要记录在Program或Global.asax入口类增加如下代码:
//3.第三步,初始扩展的业务规则引擎方法
SNF.Business.BaseRule.ExtRule = new Tony.DEMO.Business.RuleExt();
规则配置时使用方式如下:
四、规则表
用户可在系统中自定义数据存储表,二维结构,由行列组成,可将一些灵活多变的数据配置于规则表中供规则使用
1. 规则表的列由三个部分构成:
a)绑定参考项:可绑定平台、仓库,适用于多平台规则表独立维护数据;前台不可见,自动取Session中的值赋值;不是必须的。
b)查找参考项:是规则表的查询条件,使用时每个查找项必须全部匹配才能得到既定的结果;不是必须的。
c)值参考项:是规则表的返回值;必须的。
4.1、一般规则表
1. 新建一个规则表,规则表名称:承运商指派规则表,查找项:出发城市、目的城市,值项:承运商代码、承运商名称
出发地 |
目的地 |
费用 |
上海 |
苏州 |
200 |
我们根据这个表进行查找费用。
string feiyong = 单值查表("运费表","费用",字符串参数("出发地"),字符串参数("到达地"));
|
说明:通过查表函数调用:运费表,按查找项的顺序依次传入参数,即可查询得到对应的数据。
4.2、等级规则表
等级规则表就是:规则表的列中存在区间值,当调用查表函数时加入符号匹配。
根据上面的费用规则表扩展一下,我们得到:
- 规则表名称:费用表,查找项:出发地、目的地、重量下限、重量上限,值项:费用
出发地 |
目的地 |
重量下限 |
重量上限 |
费用 |
上海 |
苏州 |
20 |
200 |
200 |
string feiyong = 单值查表("运费表","费用",字符串参数("出发地"),字符串参数("到达地"),"<=" + 字符串参数("重量"),">=" +字符串参数("重量"));
返回列表("费用", feiyong ); |
4.3、多值规则表
多值规则表就是:根据同一组查找项能够查询得到一个结果集,一般用于某个结果集中存在优先级的时候
根据上面的费用表扩展一下,我们得到:
1. 规则表名称:费用表,查找项:出发地、目的地、重量下限、重量上限,值项:费用
出发地 |
目的地 |
重量下限 |
重量上限 |
费用 |
上海 |
苏州 |
20 |
200 |
200 |
上海 |
苏州 |
201 |
300 |
300 |
具体实例日后完善
4.4、规则表版本
当定义好规则表之后我们还需要为规则表新建一个版本才能够真正的使用规则表。规则表版本使得规则表在一段时间内是有效的,当过了有效期之后如果再调用就无法找到,类似于合同的期限。
比如:同一个规则表可能存在多个版本,在使用的过程中,框架会自动根据当前日期去匹配:在版本开始日期和结束日期之内的一个版本。
五、数据源
5.1、调用Sql脚本
在我们的规则里面除了一些自然方法外,我们还可以写C#方法。甚至可以直接执行sql脚本进行更新数据操作。
传入的参数当中有如下两个数据库连接,可以利用数据库连接对数据库进行操作。
IDbHelper dbHelper //业务数据库
IDbHelper userDbHelper//用户中心数据库
如:
DataTabledtData = this.DbHelper.Fill("select * from baseuser");
int r = this.DbHelper.ExecuteNonQuery("UPDATE BaseUser SET Code='' WHERE Id= 1"); |
5.2、调用服务层
在规则里还可以直接调用服务层代码。
如:
stringstateCode, message; DemoFeiYongEntity entity = new DemoFeiYongEntity(); entity.Type = 参数集["业务类型"].ToString(); entity.Money= 数值(参数集["运费"]); entity.Description = "测试哦"; SNFService.Instance.CreateService |
六、规则相关程序使用手册
6.1、规则表设计
在某些业务场景下,经常会遇到通过查表来进行逻辑判断。为保证规则开发过程的灵活性,通过“规则表设计”可以很快的根据业务需求设计出一个规则表结构,并且可以设计规则表中的字段的各项属性。说明:“参考项”即为字段的列名,“类型”分为查找参考项和值参考项(使用方法参照3.4小结),“参考条件类型”为字段存储数据的类型,如果为枚举类型在“枚举值”中可以存储枚举数据(各项用逗号隔开)。
以WMS项目中“上架分配规则”为例,业务需求:上架时可以根据不同的物料分类,上架时要指定固定的仓库、区域和一定范围内的货位。根据以上要求可以创建规则表如下图所示:
6.2、规则表管理
当“规则表”设计完成后,在“规则表管理”画面中可以维护规则表中的业务逻辑数据,维护数据时以时间段为基准,每个时间段都可以创建一个数据表。调用规则时系统会根据当前时间,找到在时间段内的数据表,获取此时间范围内的业务逻辑数据。这样可以提前设计未来一段时间内的业务逻辑,系统可以根据时间自动切换业所对应的务逻辑规则。
明细,对规则表增加数据行。
6.3、规则配置
“规则配置”画面主要负责完成具体规则程序的编写,定义的名称即为业务程序所有调用的规则名。具体规则编写方法参照以上各小节使用说明,此外还需要注意以下几点:
- 只有在平台下线状态才能编辑规则。
- 每一规则至少要有一个主规则,可以有多个子规则。
- 规则编写完后要进行上线,并且要重新登录系统后才能加载到最新规则。
注意:规则名称要是连接的字母(a-zA-Z)或者汉字
在配置规则里,可以参照“4.规则表”进行调用。
6.4、规则日志
在规则日志画面里可以看到规则在执行过程中通过“打印”函数输出的变量的结果。由于在规则调试过程中无法使用断点,但在关键节点仍然需要对程序执行过程中的中间变量进行跟踪。此时可以把所需要查看的变量通过打印函数进行输出,在规则日志中就会看到所打印的结果,从而达到调试程序的目的。规则日志结果如下图所示:
七、测试程序
BS程序调整说明 http://www.cnblogs.com/spring_wang/p/6740490.html
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
作者: 王金斗 出处: http://www.cnblogs.com/spring_wang/ Email: [email protected] QQ:903639067
QQ群:322581894
这个系列教程文档,欢迎转载:
SNF快速开发平台WinForm-CS甘特图http://www.cnblogs.com/spring_wang/p/7418423.html
SNF快速开发平台MVC-审核流,审核完成后会给下一个审核人发邮件,下一个审核人可以不登录系统,在邮件里进行审核处理http://www.cnblogs.com/spring_wang/p/7418402.html
SNF快速开发平台MVC-名片管理(实际名片样式) http://www.cnblogs.com/spring_wang/p/7416540.html
SNF快速开发平台MVC-表格单元格合并组件http://www.cnblogs.com/spring_wang/p/7416368.html
SNF快速开发平台MVC-单据状态水印http://www.cnblogs.com/spring_wang/p/7416349.html
SNF快速开发平台MVC-瀑布式分页组件http://www.cnblogs.com/spring_wang/p/7411116.html
SNF快速开发平台MVC-高级查询组件http://www.cnblogs.com/spring_wang/p/7411113.html
SNF快速开发平台MVC-自由排序组件http://www.cnblogs.com/spring_wang/p/7411090.html
SNF快速开发平台MVC-各种级联绑定方式,演示样例程序(包含表单和表格控件)http://www.cnblogs.com/spring_wang/p/7405371.html
SNF快速开发平台MVC-集成了百度开源项目echarshttp://www.cnblogs.com/spring_wang/p/7405171.html
SNF快速开发平台WinForm-平板拍照及扫描二维码功能http://www.cnblogs.com/spring_wang/p/7404600.html
SNF快速开发平台WinForm规则引擎整体介绍及使用http://www.cnblogs.com/spring_wang/p/7404182.html
SNF快速开发平台WinForm-Grid表格控件大全http://www.cnblogs.com/spring_wang/p/7403881.html
SNF快速开发平台WinForm-表单验证控件-通用http://www.cnblogs.com/spring_wang/p/7403750.html
SNF.CodeGenerator-升级生成BS页面代码-支持视图-数据库配置-快速开发者的利器http://www.cnblogs.com/spring_wang/p/7402612.html
SNF快速开发平台WinForm-审核流使用方法样例http://www.cnblogs.com/spring_wang/p/7374176.html
SNF快速开发平台WinForm-EasyQuery统计分析-效果-非常牛逼的报表查询工具http://www.cnblogs.com/spring_wang/p/7366059.html
SNF快速开发平台MVC-Grid++集成打印http://www.cnblogs.com/spring_wang/p/7365567.html
SNF快速开发平台MVC-富文本控件集成了百度开源项目editorhttp://www.cnblogs.com/spring_wang/p/7365265.html
C#按回车Enter使输入焦点自动跳到下一个TextBox的方法收集http://www.cnblogs.com/spring_wang/p/7216538.html
关于系统前端开发的那些事http://www.cnblogs.com/spring_wang/p/7092721.html
WebApi和MVC-controller层接收的json字符串的取值方法和调用后台服务方法http://www.cnblogs.com/spring_wang/p/6740314.html
SNF快速开发平台--规则引擎在程序当中如何调用http://www.cnblogs.com/spring_wang/p/6740490.html
SNF快速开发平台--规则引擎介绍和使用文档http://www.cnblogs.com/spring_wang/p/6740445.html
SNF快速开发平台MVC-EasyUI3.9之-DataGrid表格控件如何增加右键菜单http://www.cnblogs.com/spring_wang/p/6740338.html
SNF快速开发平台--多组织+多平台+多系统处理方案http://www.cnblogs.com/spring_wang/p/6734654.html
SNF快速开发平台MVC-EasyUI3.9之-Session过期处理和页面请求筛选http://www.cnblogs.com/spring_wang/p/6733975.html
SNF快速开发平台MVC-EasyUI3.9之-WebApi身份验证问题解决方案http://www.cnblogs.com/spring_wang/p/6733814.html
SNF快速开发平台MVC-EasyUI3.9之-WebApi跨域处理方案http://www.cnblogs.com/spring_wang/p/6733659.html
SNF快速开发平台MVC-EasyUI3.9之-ueditor富文本编辑在 asp.net MVC下使用步骤http://www.cnblogs.com/spring_wang/p/6710351.html
SNF开发平台WinForm之十五-时间轴控件使用-http://www.cnblogs.com/spring_wang/p/6285393.html
SNF开发平台WinForm之十四-站内发送系统信息http://www.cnblogs.com/spring_wang/p/6140031.html
SNF开发平台WinForm之十三-单独从服务器上获取PDF文件进行显示http://www.cnblogs.com/spring_wang/p/6140025.html
SNF开发平台WinForm之十二-发送手机短信功能调用http://www.cnblogs.com/spring_wang/p/6139829.html
SNF开发平台WinForm之十一-程序打包http://www.cnblogs.com/spring_wang/p/6139827.html
SNF开发平台WinForm之十-Excel导入http://www.cnblogs.com/spring_wang/p/6128604.html
SNF开发平台WinForm之九-代码生成器使用说明http://www.cnblogs.com/spring_wang/p/6128595.html
SNF开发平台WinForm之八-自动升级程序部署使用说明http://www.cnblogs.com/spring_wang/p/6128570.html
SNF开发平台WinForm之七-单据打印和使用说明http://www.cnblogs.com/spring_wang/p/6126016.html
SNF开发平台WinForm之六-上传下载组件使用http://www.cnblogs.com/spring_wang/p/6125929.html
SNF开发平台WinForm之五-高级查询使用说明-http://www.cnblogs.com/spring_wang/p/6116640.html
SNF开发平台WinForm之四-开发-主细表管理页面-http://www.cnblogs.com/spring_wang/p/6116626.html
SNF开发平台WinForm之三-开发-单表选择控件创建-http://www.cnblogs.com/spring_wang/p/6116592.html
SNF开发平台WinForm之二-开发-单表表单管理页面-http://www.cnblogs.com/spring_wang/p/6116572.html
SNF开发平台WinForm之一-开发-单表表格编辑管理页面-http://www.cnblogs.com/spring_wang/p/6116523.html
Winform开发框架之通用Windows摄像头调用拍照http://www.cnblogs.com/spring_wang/p/6008674.html
Winform开发框架之图表报表在线设计器2-图表-SNF.EasyQuery项目--SNF快速开发平台3.3-Spring.Net.Framework
Winform开发框架之图表报表在线设计器-报表-SNF.EasyQuery项目--SNF快速开发平台3.3-Spring.Net.Framework
Winform开发框架之通用附件管理模块 --SNF快速开发平台3.3-Spring.Net.Framework
SNFAutoupdater通用自动升级组件V2.0-WinForm
SNF快速开发平台3.2之--.Net可扩展的单据编号生成器-SNF.CodeRule
SNF快速开发平台3.1之--审核流(3)低调奢华,简单不凡,实例演示-SNF.WorkFlow
SNF快速开发平台3.1之--审核流(2)流程设计-SNF.WorkFlow功能使用说明
SNF快速开发平台3.1之--审核流(1)SNF.WorkFlow审核流简介
SNF快速开发平台3.0之--完美的代码生成器SNF.CodeGenerator-快速开发者的利器
基于MVC4+EasyUI的Web开发框架--Spring.Net.FrameworkV3.0总体介绍
SNF快速开发平台3.0之--MVC 打印解决方案
SNF快速开发平台3.0之--文件批量上传-统一附件管理器-在线预览文件(有互联网和没有两种)
SNF快速开发平台3.0之--asp.net mvc4 强大的导出和不需要上传文件的批量导入EXCEL
SNF快速开发平台3.0之MVC通用控件库展示-Asp.net+MVC4.0+WebAPI+EasyUI+Knockout
SNF快速开发平台3.0之BS页面展示和九大优点-部分页面显示效果-Asp.net+MVC4.0+WebAPI+EasyUI +Knockout
SNF快速开发平台3.0之-界面个性化配置+10种皮肤+7种菜单-Asp.net+MVC4.0+WebAPI+EasyUI+Knockout
SNF快速开发平台3.0之-CS页面-Asp.net+Spring.Net.Framework
SNF快速开发平台3.0之--系统里广播的作用--迅速及时、简明扼要的把信息发送给接收者