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

    在前一篇文章中,已经将Validation模块的内置的多种验证器(第一类验证器)的使用进行了介绍,今天继续后面两类验证器:独立验证器自定义验证器,同时对Validation模块下有关验证器的配置类进行遗漏补充。

 

一、独立验证器

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

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

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

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

[EntLib]微软企业库5.0 学习之路——第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——下篇其配置方式和原有的配置一样,只不过是将各个具体的验证器放到了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了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
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 == "666"
                    || string.Compare(area, "772", StringComparison.Ordinal) > 0)
                {
                    LogValidationResult(
                        validationResults,
                        "Invalid area",
                        currentTarget,
                        key);
                }
                else if (area == "000" || group == "00" || serial == "0000")
                {
                    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>,实现了以下功能:

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

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

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

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

1)方法验证

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

 

2)特性验证

这个验证方式就需要编写一个特性类,我们可以参照Validation模块内置的验证器的格式,取名为SSNValidatorAttribute,看下带代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
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进行验证

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

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

3)配置器验证

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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用以创建验证器实例进行验证。

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

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

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

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

 

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

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

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

从这张图中我们可以清楚的了解到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 学习之路系列文章索引:

第一步、基本入门

第二步、使用VS2010+Data Access模块建立多数据库项目

第三步、为项目加上异常处理(采用自定义扩展方式记录到数据库中) 

第四步、使用缓存提高网站的性能(EntLib Caching)

第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——上篇

第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——中篇 

第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——下篇

第六步、使用Validation模块进行服务器端数据验证

第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—上篇

第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—下篇

第八步、使用Configuration Setting模块等多种方式分类管理企业库配置信息

第九步、使用PolicyInjection模块进行AOP—PART1——基本使用介绍

第九步、使用PolicyInjection模块进行AOP—PART2——自定义Matching Rule

第九步、使用PolicyInjection模块进行AOP—PART3——内置Call Handler介绍

第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录

第十步、使用Unity解耦你的系统—PART1——为什么要使用Unity?

第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(1)

第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(2)

第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)

第十步、使用Unity解耦你的系统—PART3——依赖注入

第十步、使用Unity解耦你的系统—PART4——Unity&PIAB

扩展学习:

扩展学习篇、库中的依赖关系注入(重构 Microsoft Enterprise Library)[转]

 


本文转自kyo-yo博客园博客,原文链接:http://www.cnblogs.com/kyo-yo/archive/2010/08/02/Learning-EntLib-Fifth-Introduction-Validation-module-information-Part3.html,如需转载请自行联系原作者


上一篇:mybatis学习(一):mybatis执行流程


下一篇:爬取酷狗音乐Top500榜单