一、独立验证器

上篇中我将AndCompositeValidator和OrCompositeValidator归为独立验证器,这2个验证器主要是为了第一类验证服务,可以进行多种验证组合在一起进行复杂验证:

AndCompositeValidator——组合验证,逻辑与验证,所包含的多种验证全部通过则通过

OrCompositeValidator——组合验证,逻辑或验证,所包含的多种验证有一个通过则通过

这2类的验证器可以通过配置工具进行配置:

其配置方式和原有的配置一样,只不过是将各个具体的验证器放到了AndCompositeValidator或OrCompositeValidator中了。

当然也可以通过编写代码的方法进行创建:

1
2
3
4
Validator v = new AndCompositeValidator(
    new NotNullValidator(),
    new StringLengthValidator(1, 16));
v.Validate(Name4);

这样就将2个验证器统一包装到一起对Name4属性进行验证了。

注:在第一类的所有验证器由于都是继承自Validator ,所以除了通过特性、配置也可以进行代码编写进行验证

二、自定义验证

当在进行项目开发时候发现Validation模块所内置的验证器不足以满足我们日常的需要的时候,我们就需要根据根据自己的需求进行扩展,建立自定义验证。

在Validation模块下已经为我们提供了扩展接口(具体有关Validation模块的验证的实现层次可以看“上篇”,具体的验证器都是需要继承自Validator类

而具体需要实现一个自定义接口还是要思考一下步骤:

1、自定义验证器的验证方式

考虑到自定义验证器的验证方式,确定自己的自定义验证器的验证方式,是仅仅要特性验证,或者配置器验证还是2者都要?

2、开始编码

在确定确定了验证方式就可以开始着手编写具体的验证器了,我们来看下要实现不同验证方式的验证器如何编写(我这边就直接引用微软企业库给出的HOL里面的9-11一共3个例子)

在实现各种验证方式之前首先要建立一个具体的验证器,比如StringLengthValidator等,这边由于我参考的是HOL,所以我就直接引用SSNValidator.cs了:

using System;
using System.Text.RegularExpressions;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
namespace ValidationHOL.CustomValidators
{
public class SSNValidator : Validator<string>
{
public SSNValidator(string tag)
: this(tag, false)
{
}
public SSNValidator(string tag, bool ignoreHypens)
: base(string.Empty, tag)
{
this.ignoreHypens = ignoreHypens;
}
static Regex ssnCaptureRegex =
new Regex(@"^(?<area>\d{3})-(?<group>\d{2})-(?<serial>\d{4})$");
static Regex ssnCaptureNoHypensRegex =
new Regex(@"^(?<area>\d{3})(?<group>\d{2})(?<serial>\d{4})$");
private bool ignoreHypens;
protected override string DefaultMessageTemplate
{
get { throw new NotImplementedException(); }
}
protected override void DoValidate(
string objectToValidate,
object currentTarget,
string key,
ValidationResults validationResults)
{
Match match =
(ignoreHypens ? ssnCaptureNoHypensRegex : ssnCaptureRegex)
.Match(objectToValidate);
if (match.Success)
{
string area = match.Groups["area"].Value;
string group = match.Groups["group"].Value;
string serial = match.Groups["serial"].Value; if (area == ""
|| string.Compare(area, "", StringComparison.Ordinal) > )
{
LogValidationResult(
validationResults,
"Invalid area",
currentTarget,
key);
}
else if (area == "" || group == "" || serial == "")
{
LogValidationResult(
validationResults,
"SSN elements cannot be all '0'",
currentTarget,
key);
}
}
else
{
LogValidationResult(
validationResults,
this.ignoreHypens
? "Must be 9 digits"
: "Must match the pattern '###-##-####'",
currentTarget,
key);
}
}
}
}
可以看出这个验证器类还是比较简单的,这个类主要是用于验证美国社会安全号的格式正确性,这个类继承自泛型抽象类Validator<string>,实现了以下功能:

    )实现了属性DefaultMessageTemplate,返回一个异常NotImplementedException,这里我们不用去管它。

    )实现了方法DoValidate,这个是重要点,在前面的文章中也提过,这个方法主要就是用来进行具体的验证的,从方法中可以看出其本质就是通过正则表达式对社会安全号进行验证(验证规则我就不介绍了,有兴趣的可以自己搜索),如果验证不通过则通过方法LogValidationResult来记录消息及结果。

    )构造函数,这个验证有2个构造函数,构造函数接收2个参数,一个参数是验证的标签(存放一些验证信息),另一个参数ignoreHypens是表示在进行验证的时候是否忽略连字符。

 在实现完了主要的业务逻辑验证器后我们就可以开始根据验证方式进行编写对应的类了:

)方法验证

这个验证方式的话就不需要再编写任何代码了,直接实例化上面的SSNValidator后调用方法即DoValidate可进行验证。

)特性验证

这个验证方式就需要编写一个特性类,我们可以参照Validation模块内置的验证器的格式,取名为SSNValidatorAttribute,看下带代码:
using System;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
namespace ValidationHOL.CustomValidators
{
public class SSNValidatorAttribute : ValidatorAttribute
{
protected override Validator DoCreateValidator(Type targetType)
{
return new SSNValidator(this.Tag);
}
}
}

这个特性类也很简单,就是继承抽象特性类ValidatorAttribute,重载实现方法DoCreateValidator创建验证器SSNValidator进行验证

这样在具体的使用的时候只需:

[SSNValidator]
public string SSN { get; set; }

3)配置器验证

为了更好的、更方便的进行验证器,我们可以让我们自己写验证通过配置器进行配置,这时我们就需要增加一个SSNValidatorData类,这个类是用来进行和企业库的配置工具进行对接的,看下具体的代码:

using System;
using System.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.EnterpriseLibrary.Validation.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Design;
using ValidationHOL.CustomValidators.Properties;
namespace ValidationHOL.CustomValidators.Configuration
{
[ResourceDescription(typeof(Resources), "SSNValidatorDescription")]
[ResourceDisplayName(typeof(Resources), "SSNValidatorName")]
public class SSNValidatorData : ValueValidatorData
{
public SSNValidatorData()
{
}
public SSNValidatorData(string name)
: base(name, typeof(SSNValidator))
{
}
[ConfigurationProperty("ignoreHyphens")]
[ResourceDescription(typeof(Resources), "IgnoreHyphensDescription")]
[ResourceDisplayName(typeof(Resources), "IgnoreHyphensName")]
public bool IgnoreHyphens
{
get
{
return (bool)this["ignoreHyphens"];
}
set
{
this["ignoreHyphens"] = value;
}
}
protected override Validator DoCreateValidator(Type targetType)
{
return new SSNValidator(this.Tag, this.IgnoreHyphens);
}
}
}

这个配置类,主要有以下3个注意点:

1)如果想在企业库的配置工具进行配置的时候增加所配置的验证器的注释时,需要和验证消息一样将注释放入资源文件,同时在类以及对应的属性上增加特 性用以获取注释,如:[ResourceDescription(typeof(Resources), "SSNValidatorDescription")],[ResourceDisplayName(typeof(Resources), "SSNValidatorName")]

2)可以在配置器中增加属性用以从企业库配置工具中获取信息。

3)配置类必须直接或者间接继承抽象类ValueValidatorData,同时实现方法DoCreateValidator用以创建验证器实例进行验证。

完成了配置类的编写后我们还需为验证器类加上一个特性用以标识可以进行配置:

[ConfigurationElementType(typeof(SSNValidatorData))]
public class SSNValidator

重新编译后我们就可以通过配置器进行配置了,我们可以在企业库配置工具里添加一个CustomValidator,然后选择我们编写的SSNValidator:

三、遗漏补充:Validation模块下有关验证器的配置类的简单介绍

上篇我介绍了验证器和特性类的继承层次以及相关属性信息,但是遗漏了验证器在配置方面的相关信息,今天把这方面补充上,首先看下具体的结构图(这里我还是放了2种类型的验证器配置类,一个是类型转换验证器,另一个是字符串长度验证器):

从这张图中我们可以清楚的了解到Validation模块的验证器的配置类的继承层次:

IValidatorDescriptor->ValidatorData->ValueValidatorData->具体验证器配置类

接口IValidatorDescriptor

包含一个方法CreateValidator,实现类可以根据需求创建验证,同时方便企业库配置器获取所配置的具体验证类。

 

抽象类ValidatorData

实现接口IValidatorDescriptor,其作用基本类似于验证特性类BaseValidationAttribute和ValidatorAttribute的结合体,抽象了验证器创建方法、验证消息、验证结果等:

1)属性MessageTemplate,验证消息模板

2)属性MessageTemplateResourceName、MessageTemplateResourceTypeName,消息模板所在资源名和资源类型

3)属性Tag,存放验证结果

4)虚方法DoCreateValidator,用以被子类重写创建具体的验证器

5)方法IValidatorDescriptor.CreateValidator,实现接口IValidatorDescriptor的创建验证器的方法,其内部调用虚方法DoCreateValidator来获取具体的验证器

6)方法GetMessageTemplate、GetMessageTemplateResourceType,获取消息模板和根据资源类型获取消息模板

抽象类ValueValidatorData

封装了一个否定逻辑的属性,其作用基本类似于验证特性类ValueValidatorAttribute,但比ValueValidatorAttribute少了方法IsValid和FormatErrorMessage,功能单一。

 具体验证器配置类

这个类就是根据具体的业务逻辑进行创建的,其必须实现方法Validator DoCreateValidator(Type targetType)根据配置信息读取所验证的对象,然后创建具体的验证器进行验证。

抽象泛型类RangeValidatorData<T>

在上图中还有一个类RangeValidatorData<T>,这个类不同于一般业务逻辑验证器配置类,这个类是为所有需要进行范围验证的验证器配置类提供抽象:

1)泛型属性LowerBound、UpperBound,范围上限下限

2)枚举属性LowerBoundType,UpperBoundType,表示范围边界

3)这个类的泛型T必须可以实现IComparable<T>

(注:在配置类的所有属性上,如需要添加注释以方便在企业库配置 工具中显示需要和验证消息一样将注释放入资源文件,同时在类以及对应的属性上增加特性用以获取注释,如: [ResourceDescription(typeof(Resources), "SSNValidatorDescription")],[ResourceDisplayName(typeof(Resources), "SSNValidatorName")])

至此企业库Validation模块信息、验证器实现层次以及各种验证器的使用方法就介绍完了,基本都是来自于企业库的源代码以及我个人的理解,文中如有不对请大家指出。

下一篇我将继续企业库Validation模块的介绍,主要是介绍Validation模块在学习之路项目中的一些简单应用,以及企业库Validation模块所提供的Asp.net控件的简单分析。

微软企业库5.0 学习之路——第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——下篇的更多相关文章

  1. 微软企业库5.0 学习之路——第六步、使用Validation模块进行服务器端数据验证

    前端时间花了1个多星期的时间写了使用jQuery.Validate进行客户端验证,但是那仅仅是客户端的验证,在开发项目的过程中,客户端的信息永远是不可信的,所以我们还需要在服务器端进行服务器端的验证已 ...

  2. 微软企业库5.0 学习之路——第八步、使用Configuration Setting模块等多种方式分类管理企业库配置信息

    在介绍完企业库几个常用模块后,我今天要对企业库的配置文件进行处理,缘由是我打开web.config想进行一些配置的时候发现web.config已经变的异常的臃肿(大量的企业库配置信息充斥其中),所以决 ...

  3. 微软企业库5.0 学习之路——第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—下篇

    在上一篇文章中, 我介绍了企业库Cryptographer模块的一些重要类,同时介绍了企业库Cryptographer模块为我们提供的扩展接口,今天我就要根据这些 接口来进行扩展开发,实现2个加密解密 ...

  4. 微软企业库5.0 学习之路——第四步、使用缓存提高网站的性能(EntLib Caching)

    首先先补习下企业库的Caching Application Block的相关知识: 1.四大缓存方式,在Caching Application Block中,主要提供以下四种保存缓存数据的途径,分别是 ...

  5. 微软企业库5.0 学习之路——第二步、使用VS2010+Data Access模块建立多数据库项目

    现在我就开始进入学习之路的第二步——Data Access模块,这个模块是企业库中被使用频率最高的模块,它很好的封装了数据库操作应用,为我们进行多数据库系统开发提供了便利,只需更改配置文件就 可以很快 ...

  6. 微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)

    今天继续介绍Unity,在上一篇的文章中,我介绍了使用UnityContainer来注册对象之间的关系.注册已存在的对象之间的关系,同时着重介绍 了Unity内置的各种生命周期管理器的使用方法,今天则 ...

  7. [EntLib]微软企业库5.0 学习之路——第一步、基本入门

    话说在大学的时候帮老师做项目的时候就已经接触过企业库了但是当初一直没明白为什么要用这个,只觉得好麻烦啊,竟然有那么多的乱七八糟的配置(原来我不知道有配置工具可以进行配置,请原谅我的小白). 直到去年在 ...

  8. 微软企业库5.0 学习之路——第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录

    在前面的Part3中, 我介绍Policy Injection模块中内置的Call Handler的使用方法,今天则继续介绍Call Handler——Custom Call Handler,通过建立 ...

  9. 微软企业库5.0 学习之路——扩展学习篇、库中的依赖关系注入(重构 Microsoft Enterprise Library)[转]

    这篇文章是我在patterns & practices看到的一篇有关EntLib5.0的文章,主要介绍了EntLib5.0的这次的架构变化由来,觉得很不错,大家可以看一下! 在过去几年中,依赖 ...

随机推荐

  1. tomcat log4j配置

    tomcat默认的log使用的是java.util.logging,配置文件在${catalina_base}/conf/logging.properties tomcat日志分类, 1.access ...

  2. 线程阶段性总结——APM,ThreadPool,Task,TaskScheduler ,CancellationTokenSource

    不管我们使用thread,threadPool,task,还是APM异步,本质都是在使用多线程.对于新手来说,不太敢用多线程的原因,就我个人的体验来说,就是对多线程的异常捕获方式或时机缺乏了解,而一旦 ...

  3. android 布局文件中控件ID、name标签属性的命名包含“@”、“.”、“+”等等符号的含义

    1. 在项目的根目录有个配置文件“AndroidManifest.xml”,是用来设置Activity的属性的如 <?xml version="1.0" encoding=& ...

  4. [LeetCode] string整体做hash key,窗口思想复杂度O(n)。附来自LeetCode的4例题(标题有字数限制,写不下所有例题题目 T.T)

    引言 在字符串类型的题目中,常常在解题的时候涉及到大量的字符串的两两比较,比如要统计某一个字符串出现的次数.如果每次比较都通过挨个字符比较的方式,那么毫无疑问是非常占用时间的,因此在一些情况下,我们可 ...

  5. 【设计模式】 模式PK:命令模式VS策略模式

    1.概述 命令模式和策略模式的类图确实很相似,只是命令模式多了一个接收者(Receiver)角色.它们虽然同为行为类模式,但是两者的区别还是很明显的.策略模式的意图是封装算法,它认为“算法”已经是一个 ...

  6. CharSequence 去除两端空格

    CharSequence就是字符序列,String, StringBuilder和StringBuffer都是其实现类. 模仿String.trim() 实现了一个CharSequence通用的去除两 ...

  7. os模块学习(转)

    python 文件操作   一.python中文件管理 文件管理是很多应用程序的基本功能和重要组成部分.Python可以使文件管理极其简单,特别是和其它语言相对比. 1.介绍 几乎以任何语言编写的众多 ...

  8. vue-route-transition路由前进后退动画

    vue-route-transition vue router 切换动画 特性 模拟前进后退动画 基于css3流畅动画 基于sessionStorage,页面刷新不影响路由记录 路由懒加载,返回可记录 ...

  9. 【51NOD】数字1的数量

    [算法]数位DP [题解]数位dp总结 之 从入门到模板 #include<cstdio> #include<algorithm> #include<cstring> ...

  10. Mac 上真机调试cocos2d-x-3.16的test程序

    文章比较长,一个算是新手又不是新手的程序员的解决过程. 一 xcode中打开项目 首先,下载完成cocos2d-x-3.16之后,解压,然后在根目录build目录下双击cocos2d_tests.xc ...