NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(转载)
原文地址:http://www.cnblogs.com/asxinyu/p/dotnet_Opensource_project_FluentValidation_1.html
在文章:这些.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类,如下所示:
|
1
2
3
4
5
6
7
|
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>,如下面代码:
|
1
2
3
4
5
|
using FluentValidation;public class CustomerValidator : AbstractValidator<Customer> {} |
验证规则本身在验证器的构造函数中定义。为了给特定属性指定一个验证规则,需要调用RuleFor方法,通过属性的lambda表达式来进行你想要的验证。例如,确保Surname属性不是null,验证器应该这样写:
|
1
2
3
4
5
6
7
8
9
|
using FluentValidation;//Customer验证器public class CustomerValidator : AbstractValidator<Customer>{ public CustomerValidator() { RuleFor(customer => customer.Surname).NotNull(); }} |
3.针对相同属性的链式编程验证
针对同一个属性编写验证代码时,我们可以使用链式的方式进行,非常方便,也容易理解。如下面的代码:
|
1
2
3
4
5
6
7
8
|
using FluentValidation;public class CustomerValidator : AbstractValidator<Customer> { public CustomerValidator() { //Surname不为空,且不等于foo RuleFor(customer => customer.Surname).NotNull().NotEqual("foo"); }} |
上面的注释已经很明显了,针对Surname属性,直接进行判断和编写代码,同样可以写其他的,一直写下去。。。为了执行验证器,我们首先要创建一个验证器的实例对象,然后将要验证的对象传递给Validate方法,即可进行验证。如下面代码:
|
1
2
3
4
5
6
|
//要验证的对象实例Customer customer = new Customer();//验证器实例CustomerValidator validator = new CustomerValidator();//进行验证操作,获取验证结果ValidationResult results = validator.Validate(customer); |
至于结果的内容,请接着往下看。
4.验证结果
在使用验证器的Validate进行验证后,获取的ValidationResult对象里面提供了2个主要信息:
1.IsValid: 标记是否验证成功
2.Errors :错误情况,验证失败的对象集合,包括所有验证失败对象的细节。
例如下面的代码将验证失败的信息打印出来:
|
1
2
3
4
5
6
7
8
9
10
11
|
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 异常,让业务验证过程使用。主要代码如下:
|
1
2
3
|
Customer customer = new Customer();CustomerValidator validator = new CustomerValidator();validator.ValidateAndThrow(customer); |
5.2 复杂验证的处理
我们前面处理的都是单个验证器的使用,构成也基本清楚了,但如果在当前验证的实体类中还有其他对象,也需要对这个对象进行各种属性验证,该怎么办。举个例子,假设我们有一个 客户类 Customer 以及地址类Address,在Customer 中包括了一个Address类型的属性,用来存储当前客户的地址信息,如下面所示代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//客户类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验证器:
|
1
2
3
4
5
6
7
|
public class AddressValidator : AbstractValidator<Address> { public AddressValidator() { RuleFor(address => address.Postcode).NotNull(); }} |
然后我们同理要构造CustomerValidator验证器,在验证Address的时候,及可以复用上面的AddressValidator,如下面代码:
|
1
2
3
4
5
6
7
8
9
|
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,如下面代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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 组中。如下面的代码:
|
1
2
3
4
5
6
7
8
|
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")//执行默认的规则(不在集合中的) 和 MyRuleSetvalidator.Validate(person, ruleSet: "default,MyRuleSet") |
上面就是今天的内容,我们对验证器的完整过程和使用细节进行了很深入的研究,相信自己构造一个强大的验证器已经很容易了吧。接下来的内容,我们将继续介绍内置的一些验证方法和规则。对于该组件的源码可以直接从github获取,本文将在后面的文章中发布自己制作的CHM帮助文档。敬请关注!
NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(转载)的更多相关文章
- .NET平台开源项目速览(6)FluentValidation验证组件介绍与入门(一)
在文章:这些.NET开源项目你知道吗?让.NET开源来得更加猛烈些吧!(第二辑)中,给大家初步介绍了一下FluentValidation验证组件.那里只是概述了一下,并没有对其使用和强大功能做深入研究 ...
- .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序列号生成组件.今天就通过一篇简单的文章来预览一下其强大的功 ...
随机推荐
- 新手C#SQL Server使用记录2018.08.10
主键(PrimaryKey):主键就是每个数据行(记录)的唯一标识,不会有重复值的列(字段)才能当做主键.一个表可以没有主键,但是这样会很难处理表,因此一般情况表都要设置主键. 主键有两张选用策略,分 ...
- VMware-克隆机,网卡修改
1.克隆 2.修改网卡eth1为eth0 -persistent-net.rules 3.配置ip vim /etc/sysconfig/network-scripts/ifcfg-etho 4.修改 ...
- SpringMVC中在web.xml中添加中文过滤器的写法
<filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>or ...
- Spring配置连接池
---------------------siwuxie095 Spring 配置连接池 1.Spring 配置内置连接 ...
- discuz回贴通知插件实现-配置邮件服务器
添加smtp服务器,填写相应的smtp服务器,发信人地址,用户名和密码. 填写发件人地址和收件人地址来测试邮件是否发送成功.
- MVC中构建Linq条件、排序、Selector字段过滤
代码: System.Linq.Expressions.Expression<Func<Domain.S_ROLE, bool>> expressWhere1 = (c =&g ...
- Castle ActiveRecord学习(四)延迟加载、分页查询、where条件
一.延迟加载 //用户发布的主题,一对多:Table:外键表:ColumnKey:外键:Lazy:延迟加载:Cascade:级联操作(级联删除) [HasMany(typeof(ThemeInfo), ...
- 解决ios手机页面overflow scroll滑动很卡的问题
在移动端html中经常出现横向/纵向滚动的效果,但是在iPhone中滚动速度很慢,感觉不流畅,有种卡卡的感觉,但是在安卓设备上没有这种感觉; 要解决这个问题很简单: 一行代码搞定 -webkit-ov ...
- Linux tcpdump命令
一.简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据 ...
- 数学整合 新(LUOGU)
1.卡特兰数(P2532) 递推式:h(n)=C(2n,n)/(n+1) (n=0,1,2,...) 前十项(从零开始):1, 1, 2, 5, 14, 42, 132, 429, 1430, 486 ...