lovebet爱博体育官网采取优雅方式对参数验证进行拍卖。使用优雅方式对参数验证进行处理。

我们以相似的接口函数开发被,为了安全性,我们且亟待对传播的参数进行求证,确保参数按照我们所期望之限输入,如果当限制之外,如空值,不切合的种类等等,都应有为来十分要不当提示信息。这个参数的辨证处理发生强办法,最为简练的计就是使规范语句针对参数进行判定,这样的判定代码虽然好了解,但正如臃肿,如果对几近只参数、多独规范进行拍卖,那么代码就格外臃肿难以保障了,本篇随笔通过分析几种植不同之参数验证办法,最终使较为优雅的主意展开处理。

我们于一般的接口函数开发中,为了安全性,我们还亟需针对传播的参数进行验证,确保参数按照我们所期望之限定输入,如果当限以外,如空值,不吻合的路等等,都应有吃来大或者错误提示信息。这个参数的说明处理发生强主意,最为简单的法门就是是以条件语句针对参数进行判断,这样的判定代码虽然爱理解,但于臃肿,如果对大多独参数、多个条件进行处理,那么代码就老大臃肿难以保障了,本篇随笔通过分析几种不同的参数验证方式,最终采取较为优雅的方法进行拍卖。

平常会确定类型参数是否同意为空,如果是字符或出长限制,如果是整数可能用判定范围,如果是一对特种之类型比如电话号码,邮件地址等,可能需要使用正则表达式进行判断。参考随笔《C#
中参数验证措施的演化》中文章的牵线,我们本着参数的证明办法发出几乎种。

万般会确定类型参数是否允许吗空,如果是字符或发长限制,如果是整数可能用判定范围,如果是有出奇之类别比如电话号码,邮件地址等,可能需要动用正则表达式进行判定。参考随笔《C#
中参数验证措施的嬗变》中文章的介绍,我们针对参数的说明措施发生几种。

1、常规方式的参数验证

相似我们不怕是指向艺术的参数使用标准语句的方法进行判断,如下函数所示。

public bool Register(string name, int age)
{
    if (string.IsNullOrEmpty(name))
    {
        throw new ArgumentException("name should not be empty", "name");
    }
    if (age < 10 || age > 70)
    {
        throw new ArgumentException("the age must between 10 and 70","age");
    }

    //insert into db
}

或者

public void Initialize(string name, int id)
{
    if (string.IsNullOrEmpty(value))
        throw new ArgumentException("name");
    if (id < 0) 
        throw new ArgumentOutOfRangeException("id");
    // Do some work here.
}

若是复杂的参数校验,那么代码就比较臃肿

void TheOldFashionWay(int id, IEnumerable<int> col, 
    DayOfWeek day)
{
    if (id < 1)
    {
        throw new ArgumentOutOfRangeException("id", 
            String.Format("id should be greater " +
            "than 0. The actual value is {0}.", id));
    }

    if (col == null)
    {
        throw new ArgumentNullException("col",
            "collection should not be empty");
    }

    if (col.Count() == 0)
    {
        throw new ArgumentException(
            "collection should not be empty", "col");
    }

    if (day >= DayOfWeek.Monday &&
        day <= DayOfWeek.Friday)
    {
        throw new InvalidEnumArgumentException(
            String.Format("day should be between " +
            "Monday and Friday. The actual value " +
            "is {0}.", day));
    }

    // Do method work
}

有时为便利,会把参数校验的方,做一个通用的辅助类进行拍卖,如在自的公用类库里面提供了一个:参数验证的通用校验辅助类
ArgumentValidation,使用如下代码所示。

     public class TranContext:IDisposable   
     {   
         private readonly TranSetting setting=null;   
         private IBuilder builder=null;   
         private ILog log=null;   
         private ManuSetting section=null;   
         public event EndReportEventHandler EndReport;   
         public TranContext()   
         {   
        }   
        public TranContext(TranSetting setting)   
        {   
            ArgumentValidation.CheckForNullReference (setting,"TranSetting");   
            this.setting =setting;   
        }   
        public TranContext(string key,string askFileName,string operation)   
        {   
            ArgumentValidation.CheckForEmptyString (key,"key");   
            ArgumentValidation.CheckForEmptyString (askFileName,"askFileName");   
            ArgumentValidation.CheckForEmptyString (operation,"operation");   
            setting=new TranSetting (this,key,askFileName,operation);   
        }  

而这样的艺术还是不够完美,不够流畅。

1、常规方式的参数验证

貌似我们便是针对性法的参数使用口径语句的办法展开判断,如下函数所示。

public bool Register(string name, int age)
{
    if (string.IsNullOrEmpty(name))
    {
        throw new ArgumentException("name should not be empty", "name");
    }
    if (age < 10 || age > 70)
    {
        throw new ArgumentException("the age must between 10 and 70","age");
    }

    //insert into db
}

或者

public void Initialize(string name, int id)
{
    if (string.IsNullOrEmpty(value))
        throw new ArgumentException("name");
    if (id < 0) 
        throw new ArgumentOutOfRangeException("id");
    // Do some work here.
}

如若复杂的参数校验,那么代码就较臃肿

void TheOldFashionWay(int id, IEnumerable<int> col, 
    DayOfWeek day)
{
    if (id < 1)
    {
        throw new ArgumentOutOfRangeException("id", 
            String.Format("id should be greater " +
            "than 0. The actual value is {0}.", id));
    }

    if (col == null)
    {
        throw new ArgumentNullException("col",
            "collection should not be empty");
    }

    if (col.Count() == 0)
    {
        throw new ArgumentException(
            "collection should not be empty", "col");
    }

    if (day >= DayOfWeek.Monday &&
        day <= DayOfWeek.Friday)
    {
        throw new InvalidEnumArgumentException(
            String.Format("day should be between " +
            "Monday and Friday. The actual value " +
            "is {0}.", day));
    }

    // Do method work
}

突发性为好,会将参数校验的法,做一个通用的辅助类进行拍卖,如以自身之公用类库里面提供了一个:参数验证的通用校验辅助类
ArgumentValidation,使用如下代码所示。

     public class TranContext:IDisposable   
     {   
         private readonly TranSetting setting=null;   
         private IBuilder builder=null;   
         private ILog log=null;   
         private ManuSetting section=null;   
         public event EndReportEventHandler EndReport;   
         public TranContext()   
         {   
        }   
        public TranContext(TranSetting setting)   
        {   
            ArgumentValidation.CheckForNullReference (setting,"TranSetting");   
            this.setting =setting;   
        }   
        public TranContext(string key,string askFileName,string operation)   
        {   
            ArgumentValidation.CheckForEmptyString (key,"key");   
            ArgumentValidation.CheckForEmptyString (askFileName,"askFileName");   
            ArgumentValidation.CheckForEmptyString (operation,"operation");   
            setting=new TranSetting (this,key,askFileName,operation);   
        }  

可是这么的不二法门尚是不够完美,不够流畅。

2、基于第三正在类库的说明措施

当GitHub上有一部分说明类库也提供了对参数验证的成效,使用起来较便捷,采用相同种植流畅的串联写法。如CuttingEdge.Conditions对等。CuttingEdge.Condition
里面的例证代码我们来探视。

public ICollection GetData(Nullable<int> id, string xml, IEnumerable<int> col)
{
    // Check all preconditions:
    Condition.Requires(id, "id")
        .IsNotNull()          // throws ArgumentNullException on failure
        .IsInRange(1, 999)    // ArgumentOutOfRangeException on failure
        .IsNotEqualTo(128);   // throws ArgumentException on failure

    Condition.Requires(xml, "xml")
        .StartsWith("<data>") // throws ArgumentException on failure
        .EndsWith("</data>") // throws ArgumentException on failure
        .Evaluate(xml.Contains("abc") || xml.Contains("cba")); // arg ex

    Condition.Requires(col, "col")
        .IsNotNull()          // throws ArgumentNullException on failure
        .IsEmpty()            // throws ArgumentException on failure
        .Evaluate(c => c.Contains(id.Value) || c.Contains(0)); // arg ex

    // Do some work

    // Example: Call a method that should not return null
    object result = BuildResults(xml, col);

    // Check all postconditions:
    Condition.Ensures(result, "result")
        .IsOfType(typeof(ICollection)); // throws PostconditionException on failure

    return (ICollection)result;
}

public static int[] Multiply(int[] left, int[] right)
{
    Condition.Requires(left, "left").IsNotNull();

    // You can add an optional description to each check
    Condition.Requires(right, "right")
        .IsNotNull()
        .HasLength(left.Length, "left and right should have the same length");

    // Do multiplication
}

这种题方式较流畅,而且为提供了于强的参数校验方式,除了可以运用其IsNotNull、IsEmpty等内置函数,也可行使Evaluate这个扩展判断好好之函数来拍卖部分由定义的判断,应该说好满足绝大多数之参数验证要求了,唯一不好的饶是要以此第三在类库吧,有时候如果用扩大就烦一些。而且一般的话我们和好生有公用类库,如果对参数验证也还得引入一个类库,还是比辛苦一些之(个人见解)

 

2、基于第三正值类库的印证办法

当GitHub上闹局部说明类库也提供了针对参数验证的效应,使用起来比较简便,采用同一栽流畅的串联写法。如CuttingEdge.Conditions相当。CuttingEdge.Condition
里面的例子代码我们来探视。

public ICollection GetData(Nullable<int> id, string xml, IEnumerable<int> col)
{
    // Check all preconditions:
    Condition.Requires(id, "id")
        .IsNotNull()          // throws ArgumentNullException on failure
        .IsInRange(1, 999)    // ArgumentOutOfRangeException on failure
        .IsNotEqualTo(128);   // throws ArgumentException on failure

    Condition.Requires(xml, "xml")
        .StartsWith("<data>") // throws ArgumentException on failure
        .EndsWith("</data>") // throws ArgumentException on failure
        .Evaluate(xml.Contains("abc") || xml.Contains("cba")); // arg ex

    Condition.Requires(col, "col")
        .IsNotNull()          // throws ArgumentNullException on failure
        .IsEmpty()            // throws ArgumentException on failure
        .Evaluate(c => c.Contains(id.Value) || c.Contains(0)); // arg ex

    // Do some work

    // Example: Call a method that should not return null
    object result = BuildResults(xml, col);

    // Check all postconditions:
    Condition.Ensures(result, "result")
        .IsOfType(typeof(ICollection)); // throws PostconditionException on failure

    return (ICollection)result;
}

public static int[] Multiply(int[] left, int[] right)
{
    Condition.Requires(left, "left").IsNotNull();

    // You can add an optional description to each check
    Condition.Requires(right, "right")
        .IsNotNull()
        .HasLength(left.Length, "left and right should have the same length");

    // Do multiplication
}

这种书道比较流利,而且也供了较强硬的参数校验方式,除了可采用那IsNotNull、IsEmpty等内置函数,也堪运用Evaluate这个扩展判断好好之函数来拍卖部分从定义的判定,应该说可满足绝大多数底参数验证要求了,唯一不好的就是亟需用此第三着类库吧,有时候如果得扩大就烦一些。而且貌似的话我们协调来部分公用类库,如果对参数验证也还欲引入一个类库,还是于费心一些的(个人见解)

 

3、Code Contract

Code
Contracts 是微软研究院开发之一个编程类库,我不过早盼是当C#
In
Depth 的第二版本受,当时.NET
4.0尚从来不出来,当时凡是当做一个叔着类库存在的,到了.NET
4.0之后,已经参加到了.NET BCL中,该类存在于System.Diagnostics.Contracts
这个命名空间被。

夫是美其名曰:契约编程

 C#代码契约起源于微软开发的一致家研究语言Spec#(参见http://mng.bz/4147)。

    •
契约工具:包括:ccrewrite(二迈入制重写器,基于项目的设置确保契约得以贯彻履)、ccrefgen(它生成契约引用集,为客户端提供契约信息)、cccheck(静态检查器,确保代码能于编译时满足要求,而非是才检查在执行时实际会生什么)、ccdocgen(它好啊代码中指定的契约生成xml文档)。

    • 契约种类:前置条件、后置条件、固定条件、断言和要、旧式契约。

      •
代码契约工具下载和安装:下载地址Http://mng.bz/cn2k。(代码契约工具并无带有在Visual
Studio 2010惨遭,但是其核心类型位于mscorlib内。)

    • 命名空间:System.Diagnostics.Contracts.Contract

Code Contract 使得.NET
中契约式设计与编程变得尤其容易,Contract中的这些静态方法方法包括

  1. Requires:函数入口处必须满足的条件
  2. Ensures:函数出口处必须满足的尺度
  3. Invariants:所有成员函数出口处都不能不满足的标准化
  4. Assertions:在某一样触及要满足的格
  5. Assumptions:在有平沾得满足的尺度,用来压缩非必要之警戒信息

Code Contract
的利用文档您可以自官网下载及。为了方便使用Visual
Studio开发。我们得以安装一个Code Contracts for
.NET 插件。安装收尾了随后,点击Visual
Studio中之花色性质,可以看如下丰富的抉择项:

lovebet爱博体育官网 1

Contract和Debug.Assert有些地方相似:

  1. 且提供了运转时支持:这些Contracts都是可以给周转的,并且要条件不让满足,会弹出类似Assert的同的对话框报错,如下:
  2. 都得于自由的于代码中关闭打开。

不过Contract有双重多跟再强有力的作用:

  1. Contracts的企图更加分明,通过不同之Requires/Ensures等等调用,代表不同类型的规则,比仅仅的Assert更易理解以及开展活动分析
  2. Contracts的职务更统一,将3栽不同尺度还坐落代码的开端处于,而无散见在函数的开头和末段,便于寻找和分析。
  3. 差的开发人员、不同之小组、不同之铺、不同的仓库或者还见面时有发生友好之Assert,这虽大妈增加了机关分析的难度,也未便于开发人员编写代码。而Contracts直接被.NET
    4.0支持,是联合之。
  4. 它们提供了静态分析支持,这个我们得以经过部署面板看到,通过静态分析Contracts,静态分析工具得以较轻控制函数的各种有关信息,甚至可当作Intellisense

Contract中含了三只器:

  • ccrewrite, 通过奔程序集中来如二进制数据,来支持运行时检测
  • cccheck, 运行时检测
  • ccdoc, 将Contract自动生成XML文档

置于条件的拍卖,如代码所示。

       /// <summary>
        /// 实现“前置条件”的代码契约
        /// </summary>
        /// <param name="text">Input</param>
        /// <returns>Output</returns>
        public static int CountWhiteSpace(string text)
        {
            // 命名空间:using System.Diagnostics.Contracts;
            Contract.Requires<ArgumentNullException>(text != null, "Paramter:text");// 使用了泛型形式的Requires
            return text.Count(char.IsWhiteSpace);
        }

后置条件(postcondition):表示针对艺术输出的律:返回值、out或ref参数的价,以及另外被转之状态。Ensures();

        /// <summary>
        /// 实现“后置条件”的代码契约
        /// </summary>
        /// <param name="text">Input</param>
        /// <returns>Output</returns>
        public static int CountWhiteSpace(string text)
        {
            // 命名空间:using System.Diagnostics.Contracts;
            Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(text), "text"); // 使用了泛型形式的Requires
            Contract.Ensures(Contract.Result<int>() > 0); // 1.方法在return之前,所有的契约都要在真正执行方法之前(Assert和Assume除外,下面会介绍)。
                                                          // 2.实际上Result<int>()仅仅是编译器知道的”占位符“:在使用的时候工具知道它代表了”我们将得到那个返回值“。
            return text.Count(char.IsWhiteSpace);
        }

        public static bool TryParsePreserveValue(string text, ref int value)
        {
            Contract.Ensures(Contract.Result<bool>() || Contract.OldValue(value) == Contract.ValueAtReturn(out value)); // 此结果表达式是无法证明真伪的。
            return int.TryParse(text, out value); // 所以此处在编译前就会提示错误信息:Code Contract:ensures unproven: XXXXX
        }

以此代码契约功能比较强硬,不过好像对简易的参数校验,引入这么一个军火感觉麻烦,也遗落开发人员用底发出差不多大面积,而且还需要提前安装一个工具:Code
Contracts for
.NET。

所以自啊未赞成被采取这个插件的东西,因为代码要交客户采用,要求客户安装一个插件,并且打开相关的代码契约设置,还是于麻烦,如果无打开,也非会见告知客户代码编译出错,只是会当运作的时节不校验方法参数。

 

3、Code Contract

Code
Contracts 是微软研究院开发之一个编程类库,我极其早盼是当C#
In
Depth 的次本子被,当时.NET
4.0尚尚无出去,当时凡是作一个叔正类库存在的,到了.NET
4.0以后,已经进入到了.NET BCL中,该类存在于System.Diagnostics.Contracts
这个命名空间被。

本条是美其名曰:契约编程

 C#代码契约起源于微软开的平等派研究语言Spec#(参见http://mng.bz/4147)。

    •
契约工具:包括:ccrewrite(二上前制重写器,基于项目的安装确保契约得以落实实施)、ccrefgen(它生成契约引用集,为客户端提供契约信息)、cccheck(静态检查器,确保代码能当编译时满足要求,而不是只检查在执行时实际会发生什么)、ccdocgen(它好吧代码中指定的契约生成xml文档)。

    • 契约种类:前置条件、后置条件、固定条件、断言和如、旧式契约。

      •
代码契约工具下载和安装:下载地址Http://mng.bz/cn2k。(代码契约工具并无包含在Visual
Studio 2010吃,但是其主导类型位于mscorlib内。)

    • 命名空间:System.Diagnostics.Contracts.Contract

Code Contract 使得.NET
中契约式设计及编程变得更加便于,Contract中之这些静态方法方法包括

  1. Requires:函数入口处必须满足的基准
  2. Ensures:函数出口处必须满足的准绳
  3. Invariants:所有成员函数出口处都要满足的极
  4. Assertions:在某某平等接触得满足的规则
  5. Assumptions:在某个同碰一定满足的原则,用来压缩非必要的告诫信息

Code Contract
的运用文档您可以打官网下载顶。为了方便使用Visual
Studio开发。我们可以装一个Code Contracts for
.NET 插件。安装收尾了下,点击Visual
Studio中的类性质,可以看看如下丰富的挑选项:

lovebet爱博体育官网 2

Contract和Debug.Assert有些地方相似:

  1. 还提供了运行时支持:这些Contracts都是可让运行的,并且要条件不为满足,会弹出类似Assert的一样的对话框报错,如下:
  2. 都可以当任意的当代码中关闭打开。

但是Contract有更多和重强劲的效应:

  1. Contracts的用意更加鲜明,通过不同的Requires/Ensures等等调用,代表不同档次的尺度,比单纯的Assert更爱懂以及开展自动分析
  2. Contracts的职务更统一,将3种植不同条件都放在代码的起处于,而无散见在函数的开和最终,便于寻找和分析。
  3. 不等之开发人员、不同的小组、不同之店、不同之堆栈或者还见面发好之Assert,这虽大大增加了电动分析的难度,也未便于开发人员编写代码。而Contracts直接被.NET
    4.0支撑,是联的。
  4. 她提供了静态分析支持,这个我们可以通过部署面板看到,通过静态分析Contracts,静态分析工具得以比好掌握函数的各种有关消息,甚至好当做Intellisense

Contract中蕴藏了三单器:

  • ccrewrite, 通过向程序集中把如二进制数据,来支撑运行时检测
  • cccheck, 运行时检测
  • ccdoc, 将Contract自动生成XML文档

内置条件的处理,如代码所示。

       /// <summary>
        /// 实现“前置条件”的代码契约
        /// </summary>
        /// <param name="text">Input</param>
        /// <returns>Output</returns>
        public static int CountWhiteSpace(string text)
        {
            // 命名空间:using System.Diagnostics.Contracts;
            Contract.Requires<ArgumentNullException>(text != null, "Paramter:text");// 使用了泛型形式的Requires
            return text.Count(char.IsWhiteSpace);
        }

后置条件(postcondition):表示针对章程输出的律:返回值、out或ref参数的价,以及另被转的状态。Ensures();

        /// <summary>
        /// 实现“后置条件”的代码契约
        /// </summary>
        /// <param name="text">Input</param>
        /// <returns>Output</returns>
        public static int CountWhiteSpace(string text)
        {
            // 命名空间:using System.Diagnostics.Contracts;
            Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(text), "text"); // 使用了泛型形式的Requires
            Contract.Ensures(Contract.Result<int>() > 0); // 1.方法在return之前,所有的契约都要在真正执行方法之前(Assert和Assume除外,下面会介绍)。
                                                          // 2.实际上Result<int>()仅仅是编译器知道的”占位符“:在使用的时候工具知道它代表了”我们将得到那个返回值“。
            return text.Count(char.IsWhiteSpace);
        }

        public static bool TryParsePreserveValue(string text, ref int value)
        {
            Contract.Ensures(Contract.Result<bool>() || Contract.OldValue(value) == Contract.ValueAtReturn(out value)); // 此结果表达式是无法证明真伪的。
            return int.TryParse(text, out value); // 所以此处在编译前就会提示错误信息:Code Contract:ensures unproven: XXXXX
        }

本条代码契约功能于强,不过好像对简易的参数校验,引入这么一个军火感觉麻烦,也遗落开发人员用底发出多大面积,而且还亟需超前设置一个器:Code
Contracts for
.NET。

故自啊未赞成被采用这个插件的事物,因为代码要提交客户采用,要求客户安装一个插件,并且打开相关的代码契约设置,还是于辛苦,如果无打开,也未会见报客户代码编译出错,只是会在运作的时段不校验方法参数。

 

4、使用内置的公用类库处理

基于CuttingEdge.Conditions
的点子,其实我们也堪开一个类似这样的流畅性写法的校验处理,而且不需要那么烦引入第三正类库。

比如说我们当公用类库里面加一个类库,如下代码所示。

    /// <summary>
    /// 参数验证帮助类,使用扩展函数实现
    /// </summary>
    /// <example>
    /// eg:
    /// ArgumentCheck.Begin().NotNull(sourceArray, "需要操作的数组").NotNull(addArray, "被添加的数组");
    /// </example>
    public static class ArgumentCheck
    {
        #region Methods

        /// <summary>
        /// 验证初始化
        /// <para>
        /// eg:
        /// ArgumentCheck.Begin().NotNull(sourceArray, "需要操作的数组").NotNull(addArray, "被添加的数组");
        /// </para>
        /// <para>
        /// ArgumentCheck.Begin().NotNullOrEmpty(tableName, "表名").NotNullOrEmpty(primaryKey, "主键");</para>
        /// <para>
        /// ArgumentCheck.Begin().CheckLessThan(percent, "百分比", 100, true);</para>
        /// <para>
        /// ArgumentCheck.Begin().CheckGreaterThan&lt;int&gt;(pageIndex, "页索引", 0, false).CheckGreaterThan&lt;int&gt;(pageSize, "页大小", 0, false);</para>
        /// <para>
        /// ArgumentCheck.Begin().NotNullOrEmpty(filepath, "文件路径").IsFilePath(filepath).NotNullOrEmpty(regexString, "正则表达式");</para>
        /// <para>
        /// ArgumentCheck.Begin().NotNullOrEmpty(libFilePath, "非托管DLL路径").IsFilePath(libFilePath).CheckFileExists(libFilePath);</para>
        /// <para>
        /// ArgumentCheck.Begin().InRange(brightnessValue, 0, 100, "图片亮度值");</para>
        /// <para>
        /// ArgumentCheck.Begin().Check&lt;ArgumentNullException&gt;(() => config.HasFile, "config文件不存在。");</para>
        /// <para>
        /// ArgumentCheck.Begin().NotNull(serialPort, "串口").Check&lt;ArgumentException&gt;(() => serialPort.IsOpen, "串口尚未打开!").NotNull(data, "串口发送数据");
        /// </para>
        /// </summary>
        /// <returns>Validation对象</returns>
        public static Validation Begin()
        {
            return null;
        }

        /// <summary>
        /// 需要验证的正则表达式
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="checkFactory">委托</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation对象</returns>
        public static Validation Check(this Validation validation, Func<bool> checkFactory, string argumentName)
        {
            return Check<ArgumentException>(validation, checkFactory, string.Format(Resource.ParameterCheck_Match2, argumentName));
        }

        /// <summary>
        /// 自定义参数检查
        /// </summary>
        /// <typeparam name="TException">泛型</typeparam>
        /// <param name="validation">Validation</param>
        /// <param name="checkedFactory">委托</param>
        /// <param name="message">自定义错误消息</param>
        /// <returns>Validation对象</returns>
        public static Validation Check<TException>(this Validation validation, Func<bool> checkedFactory, string message)
        where TException : Exception
        {
            if(checkedFactory())
            {
                return validation ?? new Validation()
                {
                    IsValid = true
                };
            }
            else
            {
                TException _exception = (TException)Activator.CreateInstance(typeof(TException), message);
                throw _exception;
            }
        }
......

地方提供了一个正常化的反省及泛型类型检查的通用方,我们若用对参数检查,如下代码所示。

ArgumentCheck.Begin().NotNull(sourceArray, "需要操作的数组").NotNull(addArray, "被添加的数组");

苟之NotNull就是咱根据上面的定义方法进行扩张的函数,如下代码所示。

        /// <summary>
        /// 验证非空
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">输入项</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation对象</returns>
        public static Validation NotNull(this Validation validation, object data, string argumentName)
        {
            return Check<ArgumentNullException>(validation, () => (data != null), string.Format(Resource.ParameterCheck_NotNull, argumentName));
        }

一如既往道理我们可扩大更多的自定义检查措施,如引入正则表达式的处理。

ArgumentCheck.Begin().NotNullOrEmpty(libFilePath, "非托管DLL路径").IsFilePath(libFilePath).CheckFileExists(libFilePath);

它的扩充函数如下所示。

        /// <summary>
        /// 是否是文件路径
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">路径</param>
        /// <returns>Validation对象</returns>
        public static Validation IsFilePath(this Validation validation, string data)
        {
            return Check<ArgumentException>(validation, () => ValidateUtil.IsFilePath(data), string.Format(Resource.ParameterCheck_IsFilePath, data));
        }

        /// <summary>
        /// 检查指定路径的文件必须存在,否则抛出<see cref="FileNotFoundException"/>异常。
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="filePath">文件路径</param>
        /// <exception cref="ArgumentNullException">当文件路径为null时</exception>
        /// <exception cref="FileNotFoundException">当文件路径不存在时</exception>
        /// <returns>Validation对象</returns>
        public static Validation CheckFileExists(this Validation validation, string filePath)
        {
            return Check<FileNotFoundException>(validation, () => File.Exists(filePath), string.Format(Resource.ParameterCheck_FileNotExists, filePath));
        }

咱俩可根据我们的正则表达式校验,封装更多的函数进行快捷利用,如果要打定义之校验,那么就是下基础的Chek函数即可。

lovebet爱博体育官网 3

测试下代码用,如下所示。

        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            ArgumentCheck.Begin().NotNull(args, "启动参数");
            string test = null;
            ArgumentCheck.Begin().NotNull(test, "测试参数").NotEqual(test, "abc", "test");

夫ArgumentCheck作为公用类库的一个像样,因此下起来不需要再引入第三着类库,也能落实正常化的校验处理,以及可以扩大自定义的参数校验,同时也是支撑流式的书道,非常便宜。 

4、使用内置的公用类库处理

基于CuttingEdge.Conditions
的艺术,其实我们啊得以开一个近乎这样的流畅性写法的校验处理,而且未待那么辛苦引入第三方类库。

如我们于公用类库里面长一个类库,如下代码所示。

    /// <summary>
    /// 参数验证帮助类,使用扩展函数实现
    /// </summary>
    /// <example>
    /// eg:
    /// ArgumentCheck.Begin().NotNull(sourceArray, "需要操作的数组").NotNull(addArray, "被添加的数组");
    /// </example>
    public static class ArgumentCheck
    {
        #region Methods

        /// <summary>
        /// 验证初始化
        /// <para>
        /// eg:
        /// ArgumentCheck.Begin().NotNull(sourceArray, "需要操作的数组").NotNull(addArray, "被添加的数组");
        /// </para>
        /// <para>
        /// ArgumentCheck.Begin().NotNullOrEmpty(tableName, "表名").NotNullOrEmpty(primaryKey, "主键");</para>
        /// <para>
        /// ArgumentCheck.Begin().CheckLessThan(percent, "百分比", 100, true);</para>
        /// <para>
        /// ArgumentCheck.Begin().CheckGreaterThan&lt;int&gt;(pageIndex, "页索引", 0, false).CheckGreaterThan&lt;int&gt;(pageSize, "页大小", 0, false);</para>
        /// <para>
        /// ArgumentCheck.Begin().NotNullOrEmpty(filepath, "文件路径").IsFilePath(filepath).NotNullOrEmpty(regexString, "正则表达式");</para>
        /// <para>
        /// ArgumentCheck.Begin().NotNullOrEmpty(libFilePath, "非托管DLL路径").IsFilePath(libFilePath).CheckFileExists(libFilePath);</para>
        /// <para>
        /// ArgumentCheck.Begin().InRange(brightnessValue, 0, 100, "图片亮度值");</para>
        /// <para>
        /// ArgumentCheck.Begin().Check&lt;ArgumentNullException&gt;(() => config.HasFile, "config文件不存在。");</para>
        /// <para>
        /// ArgumentCheck.Begin().NotNull(serialPort, "串口").Check&lt;ArgumentException&gt;(() => serialPort.IsOpen, "串口尚未打开!").NotNull(data, "串口发送数据");
        /// </para>
        /// </summary>
        /// <returns>Validation对象</returns>
        public static Validation Begin()
        {
            return null;
        }

        /// <summary>
        /// 需要验证的正则表达式
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="checkFactory">委托</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation对象</returns>
        public static Validation Check(this Validation validation, Func<bool> checkFactory, string argumentName)
        {
            return Check<ArgumentException>(validation, checkFactory, string.Format(Resource.ParameterCheck_Match2, argumentName));
        }

        /// <summary>
        /// 自定义参数检查
        /// </summary>
        /// <typeparam name="TException">泛型</typeparam>
        /// <param name="validation">Validation</param>
        /// <param name="checkedFactory">委托</param>
        /// <param name="message">自定义错误消息</param>
        /// <returns>Validation对象</returns>
        public static Validation Check<TException>(this Validation validation, Func<bool> checkedFactory, string message)
        where TException : Exception
        {
            if(checkedFactory())
            {
                return validation ?? new Validation()
                {
                    IsValid = true
                };
            }
            else
            {
                TException _exception = (TException)Activator.CreateInstance(typeof(TException), message);
                throw _exception;
            }
        }
......

上面提供了一个正规的检查与泛型类型检查的通用方,我们而欲针对参数检查,如下代码所示。

ArgumentCheck.Begin().NotNull(sourceArray, "需要操作的数组").NotNull(addArray, "被添加的数组");

假设这个NotNull就是咱根据地方的定义方法进行扩展的函数,如下代码所示。

        /// <summary>
        /// 验证非空
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">输入项</param>
        /// <param name="argumentName">参数名称</param>
        /// <returns>Validation对象</returns>
        public static Validation NotNull(this Validation validation, object data, string argumentName)
        {
            return Check<ArgumentNullException>(validation, () => (data != null), string.Format(Resource.ParameterCheck_NotNull, argumentName));
        }

一如既往道理我们好扩大更多之自定义检查方,如引入正则表达式的拍卖。

ArgumentCheck.Begin().NotNullOrEmpty(libFilePath, "非托管DLL路径").IsFilePath(libFilePath).CheckFileExists(libFilePath);

其的恢宏函数如下所示。

        /// <summary>
        /// 是否是文件路径
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="data">路径</param>
        /// <returns>Validation对象</returns>
        public static Validation IsFilePath(this Validation validation, string data)
        {
            return Check<ArgumentException>(validation, () => ValidateUtil.IsFilePath(data), string.Format(Resource.ParameterCheck_IsFilePath, data));
        }

        /// <summary>
        /// 检查指定路径的文件必须存在,否则抛出<see cref="FileNotFoundException"/>异常。
        /// </summary>
        /// <param name="validation">Validation</param>
        /// <param name="filePath">文件路径</param>
        /// <exception cref="ArgumentNullException">当文件路径为null时</exception>
        /// <exception cref="FileNotFoundException">当文件路径不存在时</exception>
        /// <returns>Validation对象</returns>
        public static Validation CheckFileExists(this Validation validation, string filePath)
        {
            return Check<FileNotFoundException>(validation, () => File.Exists(filePath), string.Format(Resource.ParameterCheck_FileNotExists, filePath));
        }

俺们好根据我们的正则表达式校验,封装更多的函数进行快捷使,如果只要从定义的校验,那么即使使用基础之Chek函数即可。

lovebet爱博体育官网 4

测试下代码应用,如下所示。

        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            ArgumentCheck.Begin().NotNull(args, "启动参数");
            string test = null;
            ArgumentCheck.Begin().NotNull(test, "测试参数").NotEqual(test, "abc", "test");

本条ArgumentCheck作为公用类库的一个看似,因此用起来不待重新引入第三在类库,也能落实正常的校验处理,以及可以扩大自定义之参数校验,同时也是支持流式的书写道,非常好。 

相关文章