如何避免参数validation

validation原始参数和“复杂数据”

validation参数

在编写方法时,应在执行任何操作之前首先validation参数。 例如,假设我们有一个代表人的类:

public class Person { public readonly string Name; public readonly int Age; public class Person(string name, int age) { this.Name = name; this.Age = age; } } 

这个Person类出了什么问题? 在将值设置为Person字段之前,不validation名称和年龄。 “validation?”是什么意思? 应该检查两个参数,它们的值是可接受的。 例如,如果name的值是空字符串怎么办? 或者年龄的值是-10?

validation参数是通过在值不可接受时抛出ArgumentExceptions或派生exception来执行的。 例如:

 public class Person(string name, int age) { if (String.IsNullOrEmpty(name)) { throw new ArgumentNullException ("name", "Cannot be null or empty."); } if (age  120) { throw new ArgumentOutOfRangeException ("age", "Must be greater than 0 and less than 120."); } this.Name = name; this.Age = age; } 

这适当地validation了Person的构造函数接收的参数。

乏味广告恶心

因为你已经在很长一段时间内validation了参数(对吧?),你可能已经厌倦了写这些if(….)在你的所有方法中抛出Argument …语句。

我们可以做些什么来避免在整个代码中编写String.IsNullOrEmpty数十亿次?

您可以在.NET 4.0中查看代码约定 。

如果您不想等待代码合同,您可能还想查看CodePlex上的FluentValidation库 。

最终,您仍然需要将控制参数值的规则放在某处 – 这只是决定您是否更喜欢命令式样式(例如string.IsNullOrEmpty)或声明式样式。

validation输入是编写可靠代码的关键实践 – 但它肯定是重复和冗长的。

使用更复杂的类型而不是原语可能会对您有所帮助。

例如,如果您花时间定义类似PersonName类的东西,则可以在那里进行validation,而不必在每个需要在其上具有名称的其他对象上进行validation。

显然,如果您有多个使用相同字段类型的对象,这只会帮助解决问题。

您可以尝试使用Castle Validation Framework => http://www.castleproject.org/activerecord/documentation/v1rc1/usersguide/validation.html

要么

您可以使用我创建的简单validation框架。 两个框架都使用基于属性的validation。 看看下面的链接:

http://www.highoncoding.com/Articles/424_Creating_a_Domain_Object_Validation_Framework.aspx

有一些基于Postsharp的选项。 code-o-matic就是其中之一。 它允许你编写这样的代码:

 public class Person( [NotNull, NotEmpty] string name, [NotNull, NotEmpty] int age ) { this.Name = name; this.Age = age; } 

我每天都在工作。

我将用D编程语言提供解决方案。 我不知道C#generics和变量是多么强大,因为我不使用C#,但也许你可以适应这个:

 void validate(T...)(T args) { // args is variadic. foreach(arg; args) { // Iterate over variadic argument list. static if(isSomeString!(typeof(arg))) { // Introspect to see arg's type. if(arg.isNullOrEmpty) { throw new ArgException( "Problem exists between keyboard and chair."); } } else static if(isOtherTypeWithBoilerPlateValidation!(typeof(arg))) { // Do more boilerplate validation. } } } 

用法:

 class Foo { SomeType myMethod(T arg1, U arg2, V arg3) { validate(arg1, arg2, arg3); // Do non-boilerplate validation. // Method body. } } 
Interesting Posts