.NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(一)
在文章:这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑)中,给大家初步介绍了一下FluentValidation验证组件。那里只是概述了一下,并没有对其使用和强大功能做深入研究,所以今天以及接下去的几篇文章就专门介绍这个组件。不仅仅是它小,轻量级,优雅,而且一直在持续更新中。本人对这个感触很深是源于4年前自己在做一个数据过滤软件时,自己也设计了一套验证过滤的东西,虽然勉强能用,但太复杂了,复杂到我看到就想吐。。。指导我遇到了FluentValidation,彻底颠覆了我的看法,原来代码是可以很优雅的。。。这就是所谓的架构技术吧,虽然我不是很懂,但一直追求中。
为了保持内容的完整性,大部分内容我都是参考FluentValidation提供的帮助文档,自己经过翻译和理解加工。更好的呈现给大家。
.NET开源目录:【目录】本博客其他.NET开源项目文章目录
本文原文地址:.NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(一)
1.基本介绍
FluentValidation是一个使用Linq表达式,非常流畅的小型业务对象验证组件。流畅也可以说优雅。类似链式操作。易于理解,功能完善。还可以配合MVC使用直接在页面进行验证,当你看到它的语法时,非常优雅,非常令人心动。不仅可以使用Linq的操作,还能自带验证返回信息。更重要的是,组件内部已经封装好了10几种验证器。当然可以自定义一个复杂的哦。核心dll文件也不大,130多k。如果好用,可以自己移植到自己的系统哦。直接更好。目前一直在更新中,主要是bug修复。
官方网站:https://github.com/JeremySkinner/FluentValidation
NuGet Packages:Install-Package FluentValidation
ASP.NET MVC集成包:Install-Package FluentValidation.MVC5
下面我们将从一个简单的验证器的创建以及使用来介绍它的基本功能。
2.创建验证器
使用之前,要引用FluentValidation.dll,太简单,就省略了吧。为了给特定的对象定义一组验证规则,必须创建一个继承AbstractValidator<T>的类,T是需要验证的类型。例如,假设我们有一个Customer类,如下所示:
public class Customer {
public int Id { get; set; }
public string Surname { get; set; }
public string Forename { get; set; }
public decimal Discount { get; set; }
public string Address { get; set; }
}
所以按照上面要求,我们要给Customer定义一组验证规则,就要继承AbstractValidator<Customer>,如下面代码:
using FluentValidation; public class CustomerValidator : AbstractValidator<Customer>
{
}
验证规则本身在验证器的构造函数中定义。为了给特定属性指定一个验证规则,需要调用RuleFor方法,通过属性的lambda表达式来进行你想要的验证。例如,确保Surname属性不是null,验证器应该这样写:
using FluentValidation;
//Customer验证器
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(customer => customer.Surname).NotNull();
}
}
3.针对相同属性的链式编程验证
针对同一个属性编写验证代码时,我们可以使用链式的方式进行,非常方便,也容易理解。如下面的代码:
using FluentValidation;
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{ //Surname不为空,且不等于foo
RuleFor(customer => customer.Surname).NotNull().NotEqual("foo");
}
}
上面的注释已经很明显了,针对Surname属性,直接进行判断和编写代码,同样可以写其他的,一直写下去。。。为了执行验证器,我们首先要创建一个验证器的实例对象,然后将要验证的对象传递给Validate方法,即可进行验证。如下面代码:
//要验证的对象实例
Customer customer = new Customer();
//验证器实例
CustomerValidator validator = new CustomerValidator();
//进行验证操作,获取验证结果
ValidationResult results = validator.Validate(customer);
至于结果的内容,请接着往下看。
4.验证结果
在使用验证器的Validate进行验证后,获取的ValidationResult对象里面提供了2个主要信息:
1.IsValid: 标记是否验证成功
2.Errors :错误情况,验证失败的对象集合,包括所有验证失败对象的细节。
例如下面的代码将验证失败的信息打印出来:
Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
ValidationResult results = validator.Validate(customer);
//如果验证失败
if(! results.IsValid) {
//遍历所有的失败对象
foreach(var failure in results.Errors) {
//失败的属性名称,如错误信息
Console.WriteLine("Property " + failure.PropertyName + " failed validation. Error was: " + failure.ErrorMessage);
}
}
5.异常与复杂验证
5.1 如何抛出异常
上一节中,我们看到了验证结果的处理情况,但是在很多情况下,如果验证失败的情况下,要及时抛出异常给用户,所以在验证的时候就要注意抛出异常,FluentValidation也提供了这样的机制,它为验证器提供了一个ValidateAndThrow 的扩展方法。使用这个方法后,如果碰到失败的情况,会及时抛出一个ValidationException 异常,让业务验证过程使用。主要代码如下:
Customer customer = new Customer();
CustomerValidator validator = new CustomerValidator();
validator.ValidateAndThrow(customer);
5.2 复杂验证的处理
我们前面处理的都是单个验证器的使用,构成也基本清楚了,但如果在当前验证的实体类中还有其他对象,也需要对这个对象进行各种属性验证,该怎么办。举个例子,假设我们有一个 客户类 Customer 以及地址类Address,在Customer 中包括了一个Address类型的属性,用来存储当前客户的地址信息,如下面所示代码:
//客户类
public class Customer
{
public string Name { get; set; }
public Address Address { get; set; }
}
//地址类
public class Address
{
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Town { get; set; }
public string County { get; set; }
public string Postcode { get; set; }
}
由于我们也需要对Address类进行,验证,所以先类似的构造一个Address验证器:
public class AddressValidator : AbstractValidator<Address>
{
public AddressValidator()
{
RuleFor(address => address.Postcode).NotNull();
}
}
然后我们同理要构造CustomerValidator验证器,在验证Address的时候,及可以复用上面的AddressValidator,如下面代码:
public class CustomerValidator : AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(customer => customer.Name).NotNull();
//对Address使用验证器直接进行验证,可以重复使用代码
RuleFor(customer => customer.Address).SetValidator(new AddressValidator())
}
}
过程比较简单,更加复杂的处理也类似,应该没啥问题了。值得注意的是,如果Address 是集合类型,如List<Address> ,则要使用SetCollectionValidator来进行验证,和SetValidator的使用类似。
6.灵活的验证规则组设置
我们在编写验证过程中,可以编写大量的验证方法,针对不同使用场景,不同字段。但随着业务的复杂,并不是每一个验证器的使用的时候都要执行所有的验证规则。有的时候可能只需要执行一部分就可以了,否则需要针对同一个类型,编写很多个不同业务场景的验证器,显然则是非常残酷的。而FluentValidation则提供了处理这种问题的灵活性,将规则组集合在一起,并赋予一个名称,在执行的时候,可以只执行指定名称规则组的规则。看看下面的例子:
假设一个Person类有3个属性(Id,Surname,Forename),我们写一个验证器分别对几个属性进行验证,并将其中2个的验证规则放在一个规则集合里面RuleSet,名称为:Names,如下面代码:
public class PersonValidator : AbstractValidator<Person>
{
public PersonValidator()
{ //名称为 Names 的规则组
RuleSet("Names", () =>
{
RuleFor(x => x.Surname).NotNull();
RuleFor(x => x.Forename).NotNull();
});
//其他没有集合的组名称,默认为:default
RuleFor(x => x.Id).NotEqual(0);
}
}
然后我们在验证的时候,就可以灵活指定规则集的名称了,一次可以指定单个或者多个,值得注意的是,没有放在集合中的规则,默认在 default 组中。如下面的代码:
var validator = new PersonValidator();
var person = new Person();
//只执行 Names 规则集
var result = validator.Validate(person, ruleSet: "Names");
//执行 Names,MyRuleSet,SomeOtherRuleSet 规则集
validator.Validate(person, ruleSet: "Names,MyRuleSet,SomeOtherRuleSet")
//执行默认的规则(不在集合中的) 和 MyRuleSet
validator.Validate(person, ruleSet: "default,MyRuleSet")
上面就是今天的内容,我们对验证器的完整过程和使用细节进行了很深入的研究,相信自己构造一个强大的验证器已经很容易了吧。接下来的内容,我们将继续介绍内置的一些验证方法和规则。对于该组件的源码可以直接从github获取,本文将在后面的文章中发布自己制作的CHM帮助文档。敬请关注!
.NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(一)的更多相关文章
- NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(转载)
原文地址:http://www.cnblogs.com/asxinyu/p/dotnet_Opensource_project_FluentValidation_1.html 阅读目录 1.基本介绍 ...
- .NET平台开源项目速览(10)FluentValidation验证组件深入使用(二)
在上一篇文章:.NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(一) 中,给大家初步介绍了一下FluentValidation验证组件的使用情况.文章从构建间的验证器开 ...
- .NET平台开源项目速览(17)FluentConsole让你的控制台酷起来
从该系列的第一篇文章 .NET平台开源项目速览(1)SharpConfig配置文件读写组件 开始,不知不觉已经到第17篇了.每一次我们都是介绍一个小巧甚至微不足道的.NET平台的开源软件,或者学习,或 ...
- .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
不知不觉,“.NET平台开源项目速览“系列文章已经15篇了,每一篇都非常受欢迎,可能技术水平不高,但足够入门了.虽然工作很忙,但还是会抽空把自己知道的,已经平时遇到的好的开源项目分享出来.今天就给大家 ...
- .NET平台开源项目速览(13)机器学习组件Accord.NET框架功能介绍
Accord.NET Framework是在AForge.NET项目的基础上封装和进一步开发而来.因为AForge.NET更注重与一些底层和广度,而Accord.NET Framework更注重与机器 ...
- .NET平台开源项目速览(1)SharpConfig配置文件读写组件
在.NET平台日常开发中,读取配置文件是一个很常见的需求.以前都是使用System.Configuration.ConfigurationSettings来操作,这个说实话,搞起来比较费劲.不知道大家 ...
- .NET平台开源项目速览(12)哈希算法集合类库HashLib
.NET的System.Security.Cryptography命名空间本身是提供加密服务,散列函数,对称与非对称加密算法等功能.实际上,大部分情况下已经满足了需求,而且.NET实现的都是目前国际上 ...
- .NET平台开源项目速览(11)KwCombinatorics排列组合使用案例(1)
今年上半年,我在KwCombinatorics系列文章中,重点介绍了KwCombinatorics组件的使用情况,其实这个组件我5年前就开始用了,非常方便,麻雀虽小五脏俱全.所以一直非常喜欢,才写了几 ...
- .NET平台开源项目速览(9)软件序列号生成组件SoftwareProtector介绍与使用
在文章:这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑)中,给大家初步介绍了一下Software Protector序列号生成组件.今天就通过一篇简单的文章来预览一下其强大的功 ...
随机推荐
- DataTable转换为JSON数组
最后的格式为:[{},{},...] StringBuilder DataTableToJSON(DataTable dt) { string columnName; StringBuilder bu ...
- 弱省互测#0 t2
题意 给定两个字符串 A 和 B,求下面四个问题的答案: 1.在 A 的子串中,不是 B 的子串的字符串的数量. 2.在 A 的子串中,不是 B 的子序列的字符串的数量. 3.在 A 的子序列中,不是 ...
- 第一个Mac shell 小脚本
大多数程序员都喜欢偷懒的,我也不例外.相信好多Android开发的coder 在网络http请求方面,会浪费很多时间在接口调试这里..有时候,自己写了一个小测试,行还好,不行的话,还要跟写后台的哥们一 ...
- db2基础
DB2知识文档 一.db2 基础 基本语法 注释:"--"(两个减号) 字符串连接:"||" 如set msg='aaaa'||'bbbb',则msg为'aaa ...
- 大BOSS随时都会到来
郑昀(微博:http://weibo.com/yunzheng) 去年在上市前后,我不止一次跟大家说过如下内容: 我们这帮兄弟第一精通业务,第二有丰富的战斗经验和规范,你们都是中流砥柱,都要带兵打仗. ...
- 原来scanf读入字符串还能这样..
(本文针对于NOIP Day1 玩具迷题) (这是弱鸡写的)(字符串用char二维,本质一样的) 在NOIP成功AC了这道题,结果OJ上被string卡了时间,没办法只能用scanf了.....百度看 ...
- php入门一ubuntu16.04中php环境配置及一个网页
1.PHP(全称:PHP:Hypertext Preprocessor,即"PHP:超文本预处理器")是一种通用开源脚本语言. 2.PHP 文件可包含文本.HTML.JavaScr ...
- 简单正则匹配QQ邮箱
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <script src ...
- USACO翻译:USACO 2014 FEB SILVER 三题
USACO 2014 FEB SILVER 一.题目概览 中文题目名称 自动打字 路障 神秘代码 英文题目名称 auto rblock scode 可执行文件名 auto rblock scode 输 ...
- $.load()的用法
jquery load 事件用法 jquery load 事件用法 如果绑定给window对象,则会在所有内容加载后触发,包括窗口,框架,对象和图像.如果绑定在元素上,则当元素的内容加载完毕后触发. ...