抽取非基本验证到规则文件 - A2D规则引擎
基本验证与业务验证,基本验证就是始终保持不变的验证规则,可以通过如下硬编码实现:
- public class Order
- {
- [Required]
- [Range(typeof(decimal), "", "")]
- public decimal Price { get; set; }
- [Required]
- [StringLength()]
- public string Customer { get; set; }
- [Required(AllowEmptyStrings=true)]
- [StringLength()]
- public string StoreID { get; set; }
- }
然后在用如下代码validate, 把错误放到List中:
- private bool ValidateBasicRule(Order order)
- {
- List<KeyValuePair<string, string>> errors = order.IsValid();
- if (errors.Count > )
- {
- this.AddRange(errors);
- return false;
- }
- return true;
- }
- public static class DataAnnotationHelper
- {
- public static List<KeyValuePair<string, string>> IsValid<T>(this T o)
- {
- List<KeyValuePair<string, string>> errors = new List<KeyValuePair<string, string>>();
- var descriptor = GetTypeDescriptor(typeof(T));
- foreach (PropertyDescriptor propertyDescriptor in descriptor.GetProperties())
- {
- foreach (var validationAttribute in propertyDescriptor.Attributes.OfType<ValidationAttribute>())
- {
- if (!validationAttribute.IsValid(propertyDescriptor.GetValue(o)))
- {
- errors.Add(new KeyValuePair<string, string>(propertyDescriptor.Name, validationAttribute.FormatErrorMessage(propertyDescriptor.Name)));
- }
- }
- }
- return errors;
- }
- private static ICustomTypeDescriptor GetTypeDescriptor(Type type)
- {
- return new AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type);
- }
- }
然后说说业务规则的易变
SaaS程序,或者业务规则极其易变时,就要采用其他方法来做了,不可能每个公司都用设计模式分开写(虽然也行,但是不方便,公司业务规则多了后,对这些规则代码的管理就是很高的成本,而且要developer来负责)。所以要用规则文件来分开规则的编写,好处:
- 把修改的职责交给别人,比如项目经理、项目实施人员
- 代码不需要重新编译就能实现业务规则的修改
我们来解决下这个易变问题,假设有2公司:A和B。
A公司验证规则:
- 基本验证(就是Order类的验证规则的硬编码)
- 自定义验证规则:当前Order的下单网址必须来自于这几个url,如:www.cnblogs.com、www.cnblogs1.com、www.cnblogs2.com
B公司验证规则:
- 基本验证(同上)
- 自定义验证规则:无
如果用A2D规则引擎来解决的话,需要怎么做呢?
第一步当然是编写规则文件,A公司的规则文件:
- declare
- allowStores=["www.cnblogs.com", "www.cnblogs1.com", "www.cnblogs2.com"]
- end declare
- rule "test"
- when
- !_.contains(allowStores, entity.StoreID)
- then
- errors.Add("StoreID", "StoreID value not right")
- end rule
由于B公司没有自定义规则,因此不需要编写相应的规则文件
第二步,调整验证逻辑,如下:
- public class OrderService : BrokenRulesHolder
- {
- public int PlaceOrder(Order order)
- {
- this.ClearBrokenRules();
- //进行基本规则验证
- if (!ValidateBasicRule(order))
- return -;
- //进行针对不同公司的规则验证
- if (!ValidateCompanyRule(order))
- return -;
- //其他操作,比如插入数据库
- return ;
- }
- private bool ValidateCompanyRule(Order order)
- {
- BrokenRulesHolder tempBrokenRulesHolder = new BrokenRulesHolder();
- string rulePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Rules", "OrderValidations", SessionContext.CompanyID + ".r");
- using (RuleEngine engine = new RuleEngine(false)) //false代表:如果规则文件不存在不会报错,而是忽略,默认为true
- {
- engine.BindRulePath(rulePath); //将规则文件的全路径传入引擎
- engine.SetParameter("entity", order);
- engine.SetParameter("errors", tempBrokenRulesHolder);
- engine.Process();
- }
- if (tempBrokenRulesHolder.BrokenRules.Count > )
- {
- this.AddRange(tempBrokenRulesHolder.BrokenRules);
- return false;
- }
- return true;
- }
- private bool ValidateBasicRule(Order order)
- {
- List<KeyValuePair<string, string>> errors = order.IsValid();
- if (errors.Count > )
- {
- this.AddRange(errors);
- return false;
- }
- return true;
- }
- }
BrokenRule.cs代码:
- public class BrokenRulesHolder
- {
- private List<KeyValuePair<string, string>> brokenRules = new List<KeyValuePair<string, string>>();
- public List<KeyValuePair<string, string>> BrokenRules
- {
- get
- {
- return this.brokenRules.AsReadOnly().ToList();
- }
- }
- public void Add(string key, string msg)
- {
- brokenRules.Add(new KeyValuePair<string, string>(key, msg));
- }
- public void AddRange(List<KeyValuePair<string, string>> rules)
- {
- brokenRules.AddRange(rules);
- }
- public void ClearBrokenRules()
- {
- brokenRules.Clear();
- }
- }
demo代码已经更新到A2D框架中了,这里就不upload运行图了。
A2D规则引擎已经内嵌了underscore1.5.2,因此规则定义文件(.r文件)中可以写相应的underscore函数来简化写法。
规则文件说明:
- declare
- allowStores1=["www.cnblogs.com", "www.cnblogs1.com", "www.cnblogs2.com"]
- allowStores2=["www.cnblogs.com", "www.cnblogs1.com", "www.cnblogs2.com"]
- end declare
- rule "rule 1"
- when
- !allowStores1.contains(entity.StoreID)
- then
- errors.Add("StoreID", "StoreID value not right")
- end rule
- rule "rule 2"
- when
- !allowStores2.contains(entity.StoreID)
- then
- errors.Add("StoreID", "StoreID value not right")
- end rule
declare section:
- 可以不写,但是最多只能存在1个这样的section
- 每行可以有逗号,也可以没有逗号
- 这个section的本意是:当前规则文件的变量全局定义、初始化工作
- 开头为declare,小写
- 结尾为end declare,小写
rule section:
- 必须存在1到多个
- 每行可以有逗号,也可以没有逗号
- 开头为rule "一些描述",小写
- 结尾为end rule,小写
- 如果存在3个rule时,最终会变成这样的js逻辑
- 加载underscore的js代码
- 加载declare section的js代码
- if(rule1 conditions)
- {
- 执行rule1的then语句
- }
- else if(rule2 conditions)
- {
- 执行rule2的then语句
- }
- else if(rule3 conditions)
- {
- 执行rule3的then语句
- }
大家可以下载代码进行自己修改,比如可以插入自己编写的js代码来更加简化或者更加贴近项目的自定义方法、函数。
抽取非基本验证到规则文件 - A2D规则引擎的更多相关文章
- Drools 规则文件语法概述
概述(Overview) 以.drl为扩展名的文件,是Drools中的规则文件,规则文件的编写,遵循Drools规则语法.下面详细介绍一下Drools规则文件语法.具体参考官方文档: https:// ...
- [原创]java WEB学习笔记71:Struts2 学习之路-- struts2常见的内建验证程序及注意点,短路验证,非字段验证,错误消息的重用
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- Struts2的输入校验(1)——校验规则文件的编写
Struts2的输入校验(1) --校验规则文件的编写 Struts2提供了基于验证框架的输入校验,所有的输入校验只要编写配置文件,Struts2的验证框架将会负责进行服务器校验和客户端校验. 注: ...
- A2D规则引擎
A2D规则引擎 写了个简单的规则引擎,普通情况够用了: 比如2家公司有各自的利率计算规则,如下: 在C#方面,没有写在C#的业务逻辑代码中,而是移到了外部规则文件中,如(ACompanyRatePol ...
- Struts(二十四):短路验证&重写实现转换验证失败时短路&非字段验证
短路验证: 若对一个字段使用多个验证器,默认情况下会执行所有的验证.若希望前面的验证器没有通过,后面的验证器就不再执行,可以使用短路验证. 1.如下拦截器,如果输入字符串,提交表单后,默认是会出现三个 ...
- 如何在jenkins的maven项目中,用mvn命令行指定findbugs的黑名单规则文件
一:问题背景 最近在研究jenkins的过程中,针对maven项目,打算添加findbugs进行静态检查,但我不太想在项目的pom中进行修改,最好可以只修改jenkins的job配置,即配置外部化. ...
- 极其好用好学的规则引擎 - A2D规则引擎
写了个简单的规则引擎,普通情况够用了: 比如2家公司有各自的利率计算规则,如下: 在C#方面,没有写在C#的业务逻辑代码中,而是移到了外部规则文件中,如(ACompanyRatePolicy.r): ...
- AWVS11提取规则文件
在这里给大家分享一个获取AWVS规则文件的思路. 目前我提取的是17年4月份的扫描规则. 后面如果规则更新,可以自行提取 官网: https://www.acunetix.com/vulne ...
- .NET开源工作流RoadFlow-Bug修改-1.8.2表单验证时ueditor编辑非空验证无效
RoadFlow生成的表单,Ueditor编辑器不能进行非空验证的BUG修改: 1.修改控制器:WorkFlowFormDesignerController红框处: 2.修改js文件:Scripts/ ...
随机推荐
- MFC更换画笔(画刷)颜色以及画眼睛(GDI画图)
MFC画眼睛 换画笔(画刷)颜色(参考链接:https://blog.csdn.net/sunxiving/article/details/51272001) 由于画笔一旦创建后就无法修改.所以要修改 ...
- (其他)window10上好用的软件
1.everything:比我用电脑搜索快一些,(常用的搜索其实熟悉电脑的都会,不过想快一点) 如果你曾对效率工具有过研究,想必对 Everything 的名字不会陌生.这款仅有 1.3 MB 的小软 ...
- LeetCode题解之Keys and Rooms
1.题目描述 2.问题分析 使用深度优先遍历 3.代码 bool canVisitAllRooms(vector<vector<int>>& rooms) { int ...
- Linux 最小化安装后IP的配置(手动获取静态IP地址)
一.图形化界面配置(假设为电脑A) 如果你的Linux安装有图形化界面,那么通过以下方式来配置: 我这里是有两块网卡,第一个网卡在上篇中已经通过DHCP来配置了:Linux 最小化安装后IP的配置(D ...
- 后台调用前端JS
ClientScript.RegisterStartupScript(ClientScript.GetType(), "myscript", "<script> ...
- C#学习之接口
什么是接口?其实,接口简单理解就是一种约定,使得实现接口的类或结构在形式上保持一致.个人觉得,使用接口可以使程序更加清晰和条理化,这就是接口的好处,但并不是所有的编程语言都支持接口,C#是支持接口的. ...
- CentOS 7.0安装
CentOS 7.0安装 本次通过虚拟机的方法安装CentOS 7.0操作系统,开启虚拟机后会出现以下界面 1.选择第一项,Install CentOS 7 (安装CentOS 7),进入下面的界面 ...
- centos7如何安装gcc5.4
由于需要使用到cilk plus和std=c++14,所以决定将编译器升级. 基本教程如下: 1.下载GCC源码: wget ftp://mirrors.kernel.org/gnu/gcc/gcc- ...
- 【转】10条你不可不知的css规则
10条你不可不知的css规则 Posted on 2006-12-20 10:33 雨中太阳 阅读(343) 评论(1) 编辑 收藏 :[译]10条你不可不知的css规则正文: Published D ...
- 新近碰到的病毒(TR.Spy.Babonock.A)
先来段Microsoft的说明: Worm:Win32/Babonock.A Alert level: Severe Detected with Windows Defender Antivirus ...