基本验证与业务验证,基本验证就是始终保持不变的验证规则,可以通过如下硬编码实现:

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来负责)。所以要用规则文件来分开规则的编写,好处:

  1. 把修改的职责交给别人,比如项目经理、项目实施人员
  2. 代码不需要重新编译就能实现业务规则的修改

我们来解决下这个易变问题,假设有2公司:A和B。

A公司验证规则:

  1. 基本验证(就是Order类的验证规则的硬编码)
  2. 自定义验证规则:当前Order的下单网址必须来自于这几个url,如:www.cnblogs.com、www.cnblogs1.com、www.cnblogs2.com

B公司验证规则:

  1. 基本验证(同上)
  2. 自定义验证规则:无

如果用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. 可以不写,但是最多只能存在1个这样的section
  2. 每行可以有逗号,也可以没有逗号
  3. 这个section的本意是:当前规则文件的变量全局定义、初始化工作
  4. 开头为declare,小写
  5. 结尾为end declare,小写

rule section:

  1. 必须存在1到多个
  2. 每行可以有逗号,也可以没有逗号
  3. 开头为rule "一些描述",小写
  4. 结尾为end rule,小写
  5. 如果存在3个rule时,最终会变成这样的js逻辑
  6. 加载underscore的js代码
    
    加载declare section的js代码
    
    if(rule1 conditions)
    {
    执行rule1的then语句
    }
    else if(rule2 conditions)
    {
    执行rule2的then语句
    }
    else if(rule3 conditions)
    {
    执行rule3的then语句
    }

大家可以下载代码进行自己修改,比如可以插入自己编写的js代码来更加简化或者更加贴近项目的自定义方法、函数。

抽取非基本验证到规则文件 - A2D规则引擎的更多相关文章

  1. Drools 规则文件语法概述

    概述(Overview) 以.drl为扩展名的文件,是Drools中的规则文件,规则文件的编写,遵循Drools规则语法.下面详细介绍一下Drools规则文件语法.具体参考官方文档: https:// ...

  2. [原创]java WEB学习笔记71:Struts2 学习之路-- struts2常见的内建验证程序及注意点,短路验证,非字段验证,错误消息的重用

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  3. Struts2的输入校验(1)——校验规则文件的编写

    Struts2的输入校验(1) --校验规则文件的编写 Struts2提供了基于验证框架的输入校验,所有的输入校验只要编写配置文件,Struts2的验证框架将会负责进行服务器校验和客户端校验. 注: ...

  4. A2D规则引擎

    A2D规则引擎 写了个简单的规则引擎,普通情况够用了: 比如2家公司有各自的利率计算规则,如下: 在C#方面,没有写在C#的业务逻辑代码中,而是移到了外部规则文件中,如(ACompanyRatePol ...

  5. Struts(二十四):短路验证&重写实现转换验证失败时短路&非字段验证

    短路验证: 若对一个字段使用多个验证器,默认情况下会执行所有的验证.若希望前面的验证器没有通过,后面的验证器就不再执行,可以使用短路验证. 1.如下拦截器,如果输入字符串,提交表单后,默认是会出现三个 ...

  6. 如何在jenkins的maven项目中,用mvn命令行指定findbugs的黑名单规则文件

    一:问题背景 最近在研究jenkins的过程中,针对maven项目,打算添加findbugs进行静态检查,但我不太想在项目的pom中进行修改,最好可以只修改jenkins的job配置,即配置外部化. ...

  7. 极其好用好学的规则引擎 - A2D规则引擎

    写了个简单的规则引擎,普通情况够用了: 比如2家公司有各自的利率计算规则,如下: 在C#方面,没有写在C#的业务逻辑代码中,而是移到了外部规则文件中,如(ACompanyRatePolicy.r): ...

  8. AWVS11提取规则文件

    在这里给大家分享一个获取AWVS规则文件的思路.  目前我提取的是17年4月份的扫描规则.   后面如果规则更新,可以自行提取 官网:   https://www.acunetix.com/vulne ...

  9. .NET开源工作流RoadFlow-Bug修改-1.8.2表单验证时ueditor编辑非空验证无效

    RoadFlow生成的表单,Ueditor编辑器不能进行非空验证的BUG修改: 1.修改控制器:WorkFlowFormDesignerController红框处: 2.修改js文件:Scripts/ ...

随机推荐

  1. [20190226]测试使用bbed恢复索引.txt

    [20190226]测试使用bbed恢复索引.txt --//上午做tab$删除恢复测试时发现,tab$的索引i_tab1很小.可以尝试使用bbed解决这个问题.--//首先在普通表上做一个测试看看. ...

  2. python shell与反弹shell

    python shell与反弹shell 正常shell需要先在攻击端开机情况下开启程序,然后攻击端运行程序,才能连接 反弹shell,攻击端是服务端,被攻击端是客户端正常shell,攻击端是客户端, ...

  3. C++多线程同步技巧(三)--- 互斥体

    简介 Windows互斥对象机制. 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问,在线程同步与保证程序单体运行上都有相当大的用处. 代码 ...

  4. Java监控类库Metrics

    Gauge含义:瞬时值值类型:不限 Counter:作用:可以insr, decr 的计数器值类型:数字 Histogram:含义:maximum, mean, etc., it also measu ...

  5. 基于WIN8.1:新手篇→tomcat安装配置

    一.JDK配置 下载安装JDK和tomcat 打开电脑属性,高级系统设置进行环境变量配置 新建系统变量,变量值为JDK安装路径,并在系统变量path最后加上“%JAVA_HOME%\bin;%JAVA ...

  6. VMare Workstation 安装Ubuntu 虚拟机教程

    1.VMware Workstation,选择左上角文件—新建虚拟机,开始新建一台虚拟机,典型的话许多配置为默认设置,因此,这里我选择自定义安装: 2.机硬件兼容性选择默认即可: 3.客户操作系统选择 ...

  7. Golang 并发简介

    并发概要 随着多核CPU的普及, 为了更快的处理任务, 出现了各种并发编程的模型, 主要有以下几种: 模型名称 优点 缺点 多进程 简单, 隔离性好, 进程间几乎无影响 开销最大 多线程 目前使用最多 ...

  8. 自定义实现HashMap的put、get方法

    public class HashMap{ public static void main(String[] args){ put("aa", "wo ai ni&quo ...

  9. FCM算法的matlab程序2

    FCM算法的matlab程序2 在“FCM算法的matlab程序”这篇文章中已经用matlab程序对iris数据库进行实现,并求解准确度.下面的程序是另一种方法,是最常用的方法:先初始化聚类中心,在进 ...

  10. S/4 HANA中的MATDOC和MATDOC_EXTRACT

    最近做了销售和物料管理方面的一些需求,因此对S/4中的MM的数据模型有了一定的了解.目前网络已经有一些介绍物料凭证表MATDOC的文章,内容好像不是很详细,另外也没发现介绍库存变更数据表MATDOC_ ...