Evolution of parameter verification methods in C #

Source: Internet
Author: User

Generally, when writing a method, the first step is to perform parameter verification, which also reflects the attention and care of the coders. However, in many cases, this process is boring and tedious, for example, when an API design document is obtained, it usually specifies whether the type parameter is allowed to be null. If it is a character, there may be length restrictions. If it is an integer, you may need to determine the range, if it is a special type such as phone number or email address, you may need to use a regular expression for determination. Generally, we usually make condition judgments at the beginning of the method, and then throw an appropriate exception. This is the most common and common practice, but in. NET, using some language features and class libraries, you can use some other methods to free us from complicated and tedious work. This article describes the methods that can be used for parameter verification. They include direct judgment statements, help classes, extension methods, Customer Attribute, Enterprise Liberary, Debug. Assert, and Code Contract. You can see in. with the evolution of the version, NET gradually adds a lot of Declarative programming (Declarative programming) styles, such code will directly show what rather than how, so that the code is clearer and easier to maintain. Now let's look at the methods for verifying these parameters. A general method assumes that we have a method as follows for registration and registration. We need to input the name and age. Public bool Register (string name, int age) {// insert into db}. Of course, our method can be called if nothing is passed in. Generally, the first thing we need to do is to verify the validity of the parameters. For example, if you want to participate in the Shanghai International Marathon, you need to be older than 10 years and less than 70 years old. The general verification method is as follows: public bool Register (string name, int age) {if (string. isNullOrEmpty (name) {throw new ArgumentException ("name shocould not be empty", "name");} if (age <10 | age> 70) {throw new ArgumentException ("the age must between 10 and 70", "age");} // insert into db} we will find that if every method is determined in this way, it is very troublesome and cumbersome. So I thought of extracting it into a help method. Public static class ArgumentHelper {public static void RequireRange (int value, int minValue, int maxValue, string argumentName) {if (value> maxValue | value <minValue) {throw new ArgumentException (string. format ("The value must be between {0} and {1}", minValue, maxValue), argumentName) ;}} public static void RequireNotNullOrEmpty (string value, string argumentName) {if (string. isNullOrEmpty (Value) {throw new ArgumentException ("The value can't be null or empty", argumentName) ;}} in this way, in all The places where interval verification and non-empty verification are required, call the methods in this help class. Public bool Register (string name, int age) {ArgumentHelper. requireNotNullOrEmpty (name, "name"); ArgumentHelper. requireRange (age, 3.0, "age"); // insert into db} in C #, the extension method is introduced, therefore, we can perform parameter verification in a more elegant way. We will rewrite the previous help method as follows: public static class ArgumentHelper {public static void RequireRange (this int value, int minValue, int maxValue, string argumentName) {if (value> maxValue | value <minValue) {throw new ArgumentException (string. format ("The value must be between {0} and {1}", minValue, maxValue), argumentName) ;}} public static void RequireNotNullOrEmpty (this string value, string argumentName) {if (string. isNullOrEmpty (value) {throw new ArgumentException ("The value can't be null or empty", argumentName) ;}} so that our verification is changed to The following: public bool Register (string name, int age) {name. requireNotNullOrEmpty ("Name"); age. requireRange (10, 70, "age"); // insert into db} with the extension method, you can write a lot of smooth validation statements similar to LINQ. Some similar verification libraries provide similar functions. Such as FluentValidation and CuttingEdge. Conditions. For example, this example is taken from 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 fai Lure. 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 shocould not return nul L object result = BuildResults (xml, col); // Check all postconditions: Condition. ensures (result, "result "). isOfType (typeof (ICollection); // throws PostconditionException on failure return (ICollection) result;} You can use the extension method to write such funny statements as in. Who write like this two uses the class library or framework in addition to their own writing method, some class libraries and frameworks also provide parameter verification modules. Enterprise Liberary the Microsoft Enterprise Library (Enterprise Liberary) provides a component named Validation Application Block for verification. After the installation, you can run entlibconfig.exe to add the verification interface or use the previous Code as an example. We encapsulate name and age as a field of the class named Person, and then use the Enterprise Library for verification. Allow entlibconfig.exe, load the compiled dll or exe, select the field or method to be verified, and add the appropriate verification rules. For example, after Validation with Enterprise Liberary is completed, save it as an app. <configuration> <configSections> <section name = "validation" type = "Microsoft. practices. enterpriseLibrary. validation. configuration. validationSettings, Microsoft. practices. enterpriseLibrary. validation, Version = 5.0.414.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35" RequirePermission = "true"/> </configSections> <validation> <type name = "ValidationConsole. program + Person "defaultRuleset =" Validation Ruleset "assemblyName =" ValidationConsole, Version = 1.0.0.0, Culture = neutral, publicKeyToken = null "> <ruleset name =" Validation Ruleset "> <properties> <property name =" Name "> <validator type =" Microsoft. practices. enterpriseLibrary. validation. validators. notNullValidator, Mic Rosoft. practices. enterpriseLibrary. validation, Version = 5.0.414.0, Culture = neutral, publicKeyToken = 31bf3856ad364e35 "messageTemplate =" name cannot be blank "name =" Not Null Validator "/> </property> <property name =" Age "> <validator type =" Microsoft. practices. enterpriseLibrary. validation. validators. rangeValidator, Microsoft. practices. enterpriseLibrary. validation, Version = 5.0.414.0, Culture = neutral, PublicKeyToken = 31 Bf3856ad364e35 "culture =" zh-CN "lowerBound =" 10 "lowerBoundType =" Exclusive "upperBound =" 70 "messageTemplate =" Age showould between & # xD; & # xA; 10 and 70 & # xD; & # xA; "name =" Range Validator "/> </property> </properties> </ruleset> </type> </validation> </configuration> you can see that the Enterprise Library actually generates app. config file, and then write the parameter validation conditions in the file, and then reference the dll of the Enterprise Library for verification during running. Parameter verification can be configured. The specific usage is as follows: public class Person {public string Name {get; set;} public int Age {get; set ;} public Person (string name, int age) {this. name = name; this. age = age ;}} static void Main (string [] args) {Validator <Person> customerValidator = ValidationFactory. createValidator <Person> ("Validation Ruleset"); Person myCustomer = new Person ("admin", 9); ValidationResults validateResult = customer Validator. Validate (myCustomer); if (! ValidateResult. isValid) {for (int I = 0; I <validateResult. count; I ++) {Console. writeLine ("verification error {0}:" + validateResult. elementAt (I ). message, I + 1) ;}} else {Console. writeLine ("correct");} Console. readKey ();} running result: Validate using enterprise liberary ASP.. net mvc can also use custom attributes for parameter verification. ASP. net mvc Model uses the Data Annotations attribute for verification. Data Annotations are actually a series of custom Attribute classes inherited from attributes that can be used in class or class attributes. System. componentModel. dataAnnotations Contains classes such as Required, Range, RegularExpression, and StringLength. These custom attribute classes are inherited from ValidationAttribute abstract class: public abstract class ValidationAttribute: attribute {public string ErrorMessage {get; set;} public virtual bool IsValid (object value); protected virtual ValidationResult IsValid (object value, ValidationContext validationContext ); // other members. N In et mvc, our Person Model can be written as follows: public class Person {[Required] public string Name {get; set;} [Range (10, 70)] public int Age {get; set ;}} is very simple. When writing an object class, you can give the verification rules by the way. In this way, we are instantiating the Person class. If the condition is not met, an exception will be thrown. Some commercial software of PostSharp has achieved ultimate in property verification, such as the commercial software of PostSharp. The following figure shows the website's publicity page: postsharp. In the method parameters, you can use custom attributes to mark them and then perform dynamic verification when the system is running. PostSharp uses a so-called Static injection method, that is, injecting IL code into the type or method of the compiled assembly. It is during code compilation, instead of injecting it at runtime. Visual Studio uses MSBuild to execute the generation process. PostSharp inserts itself into the code generation process as a series of Build tasks. For more information about the principles, see the article "AOP: PostSharp Principle Analysis" under. NET. Here I reference a picture in this article, which vividly illustrates the principle of PostSharp: Post is actually very easy to verify by using attributes. We can also implement functions similar to PostSharp by ourselves, before using the Customer Attribute, you must first understand the Attribute class in Chinese. net programming applications. The following describes how to use custom attributes in PostSharp to mark and verify parameters. In fact, you have read System. ComponentModel. DataAnnotations in ASP. net mvc to know how to implement it. First, create an ArgumentValidationAttribute abstract class. As agreed, all class names inherited from Attribute must be followed by Attribute. This class has only one abstract method, Validate, for verification. Public abstract class ArgumentValidationAttribute: Attribute {public abstract void Validate (object value, string argumentName);} Then, we define a custom Attribute NotNullAttribute to verify non-null values. Note that on this class, the AttributeUsage attribute is used. In its constructor parameters, AttributeTargets is passed in. the Parameter Enumeration indicates that the tag can only be used on parameters of the method. [AttributeUsage (AttributeTargets. parameter)] public class notnullattrition: ArgumentValidationAttribute {public override void Validate (object value, string argumentName) {if (value = null) throw new ArgumentNullException (argumentName );}} then an InRangeAttribute is defined to verify the range. Here we define a constructor that can pass in a range. [AttributeUsage (AttributeTargets. parameter)] public class InRangeAttribute: ArgumentValidationAttribute {private int min; private int max; public InRangeAttribute (int min, int max) {this. min = min; this. max = max;} public override void Validate (object value, string argumentName) {int intValue = (int) value; if (intValue <min | intValue> max) {throw new ArgumentOutOfRangeException (argumentNam E, string. format ("min = {0}, max = {1}", min, max) ;}} has the above two classes, we also need to call these verification methods in a large framework class, which is usually implemented using methods such as interface injection. Only key parts are listed here. Public class ValidationInterceptor: IInterceptor {public void Intercept (IInvocation invocation) {ParameterInfo [] parameters = invocation. method. getParameters (); for (int index = 0; index <parameters. length; index ++) {var paramInfo = parameters [index]; var attributes = paramInfo. getCustomAttributes (typeof (ArgumentValidationAttribute), false); if (attributes. length = 0) continue; foreach (Argum EntValidationAttribute attr in attributes) {attr. validate (invocation. arguments [index], paramInfo. name) ;}} invocation. proceed () ;}} then, let's look back at our code. First, we abstract an IRegister interface: public interface IRegister {void Register ([NotNull] string name, [InRange (10, 70)] int age);} You can see that the method and parameter in the interface can be written before the attribute defined previously for verification, after parameter verification rules are defined in the interface method, you do not need to define them again in all methods that implement the interface. Our registration class only needs to implement this interface, and then perform unified verification before executing Register. Public class ShMarathon: IRegister {public void Register (string name, int age) {// doesn't need to validate // insert into db} This method is actually an idea of AOP (Aspect-Oriented Programming, for more information, see AOP in. NET: Practical Aspect-Oriented Programming and Dependency Injection in. NET three Code ContractCode Contracts is a programming class library developed by Microsoft Research Institute. I first saw it In the second version of C # In Depth, at that time. NET 4.0 has not been released yet. It existed as a third-party class library.. NET 4.0 has been added. net bcl, which exists in System. diagnostics. co In the namespace ntracts. Namespace System. diagnostics. contracts {// Summary: // Contains static methods for representing program contracts such as preconditions, // postconditions, and object invariants. public static class Contract {public static event EventHandler <ContractFailedEventArgs> ContractFailed; public static void Assert (bool condition); public static void Assert (bool condition, string userMessage); public sta Tic void Assume (bool condition); public static void Assume (bool condition, string userMessage); public static void EndContractBlock (); public static void Ensures (bool condition ); public static void Ensures (bool condition, string userMessage); public static void EnsuresOnThrow <TException> (bool condition) where TException: Exception; public static void EnsuresOnThrow <TException> (bool condition, str Ing userMessage) where TException: Exception; public static bool Exists <T> (IEnumerable <T> collection, Predicate <T> predicate); public static bool Exists (int fromInclusive, int toExclusive, predicate <int> predicate); public static bool ForAll <T> (IEnumerable <T> collection, Predicate <T> predicate); public static bool ForAll (int fromInclusive, int toExclusive, predicate <int> predicate); public static Void Invariant (bool condition); public static void Invariant (bool condition, string userMessage); public static T OldValue <T> (T value ); public static void Requires <TException> (bool condition) where TException: Exception; public static void Requires (bool condition); public static void Requires (bool condition, string userMessage ); public static void Requires <TException> (bool condition, string user Message) where TException: Exception; public static T Result <T> (); public static T ValueAtReturn <T> (out T value);} Code Contract to make. in NET, contractual design and programming become easier. In Contract, these static methods include Requires: conditions that must be met at the function entry Ensures: conditions that must be met at the function exit Invariants: conditions that must be met at the exit of all member functions Assertions: conditions that must be met at a certain point Assumptions: conditions that must be met at a certain point, to reduce unnecessary warning information, you can download the usage document Code Contract from the official website. To facilitate Visual Studio development. We can install a Code Contracts Editor Extensions plug-in. After the installation is complete, click Project Properties in Visual Studio and you will see the following rich options: code contract for visual studio now, in our Register method, you can use Contract for judgment, usage and Debug. assert is similar to: public static bool Register (string name, int age) {Contract. requires (! String. isNullOrEmpty (name); Contract. requires (age> 10 & age <70); // insert into db return false;} When an incorrect age value is input, the following error occurs: PreconditonFailed Contract and Debug. assert is similar in some aspects: it provides runtime support: these Contracts can be run, and once the conditions are not met, an error similar to Assert dialog box will pop up, as shown below: you can close it in the code at will. However, Contract has more and more powerful functions: Contracts has clearer intentions and uses different Requires/Ensures to call different types of conditions, it is easier to understand and automatically analyze the positions of Contracts than simply Assert. Three different conditions are put at the beginning of the Code, rather than at the beginning and end of the function, easy to search and analyze. Different developers, groups, companies, and libraries may have their own Assert, which greatly increases the difficulty of automatic analysis and is not conducive to coding. Contracts is directly supported by. NET 4.0 and is unified. It provides support for static analysis. We can see through the configuration panel that through static analysis Contracts, static analysis tools can easily master various information about functions, it can even be used as an intelliisensecontract tool that contains three tools: ccrewrite. By concentrating some binary data into the program, it can detect cccheck and ccdoc at run time, using Contract to automatically generate XML documents is the principle of Contract. introduction to new features in NET 4.0: Design By Contracts, which is why it is better than Debug. the reason for the powerful Assert is that we only need to write all the conditions for pre-execution judgment and post-execution judgment to one place, and then compile the code, ccrewrite will help us generate the corresponding code, save the start value and insert the corresponding code to the proper position of the method. This makes our code more clean and easy to maintain. Code Contract 4 Summary This article briefly introduces in. methods used to verify method parameters, including writing judgment statements before method execution, extracting them to public help classes, using extension methods, and some class libraries such as Enterprise Liberary, postSharp, ASP. net mvc then implements a simple example of using custom attributes for method parameter verification, and finally introduces it. NET 4.0 types of Code Contract. during development, these verification methods can unify our method parameter verification and reduce the workload in a certain program. I hope this article will help you.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.