Extended C # version of Kevin McFarlane's DesignByContract Framework

Source: Internet
Author: User
The C # version of Kevin McFarlane's DesignByContract Framework has almost become a de facto standard used by many friends in C # development since its release in CodeProject 02. Based on his experience in using this framework, this article uses Strategy Pattern to further expand Kevin's original version and simplify the most common inspection semantics. The source code improved in this article is published using the Public Domain Protocol. That is to say, there are no restrictions at all.

If you want to use this code, keep the comment at the top of the source code file.

Kevin McFarlane's C # edition DesignByContract Framework implementation in CodeProject.com original address: http://www.codeproject.com/csharp/designbycontract.asp

Download the improved version of DesignByContract source code and test project Source Code (the test project is in the VS2005 VSTS test project format): DesignByContract_Enhanced_Version.zip

Introduction

For the basic usage of this framework, see the original text written in CodeProject.com by Kevin McFarlane.

The following describes how to use the extension.

Enable Assertion of Trace or Debug

Similar to the original version, by default, methods such as Check. Require () Fail to throw errors such as PreconditionException. You can add USE_TRACE_ASSERTION or USE_DEBUG_ASSERTION to the Conditional compilation symbols of the project. The two symbols indicate that the System. Diagnostics. Trace. Assert () or System. Diagnostics. Debug. Assert () prompts to check the failure message, instead of throwing an exception by default.

When using these two symbols, you can use the following code to change the default error message or logging method in the startup initialization code of the Code (for example, Application_Start of Global. asax:

System. Diagnostics. Trace. Listeners. Clear ();
System. Diagnostics. Trace. Listeners. Add (new TextWriterTraceListener (Console. Out ));

NOTE 1: For ASP. NET programs, always use USE_DEBUG_ASSERTION.
NOTE 2: By default ,. the trace and debug of the net 2.0 program project are enabled by default in the Debug compilation mode of the project, and the trace is enabled by default in the Release compilation mode. The debug mode is not enabled by default. However, you can manually modify these two settings in project properties.

Modify the text template of the error message

In the original version, the default error prompt is in English and hardcode is directly used and scattered in various source code methods. If we want to change the error prompt type, it is not that convenient. In this release version, all text templates of error message are put in # region Const Literals at the beginning of the Check class definition of the source file, so that you can easily modify them. To read this information from an external resource file, you can change the variables in # region Const Literals to private static readonly, and read from the external resource file in the static constructor of Check.

Check logic encapsulation and usage based on Strategy Mode

The biggest improvement in the ultimate version is the addition of a set of Check Strategies. All Check Strategy interfaces implement the ICheckStrategy interface and define static member variables in the Check class to facilitate access to their instances.

ICheckStrategy is defined as follows:

1 public interface ICheckStrategy
2 {
3 bool Pass (object obj );
4 string GetFailingMessage (string objName );
5}


The Pass method needs to implement the check logic for obj. If the return value is true, the check is passed. The GetFailingMessage method is used to return the error message.

This improved version provides the following built-in Check Strateies:

NotNull-can be used to check whether any object is null
NotNullOrEmpty-can be used to check whether objects of the string, Array, or ICollection type are non-null and non-empty. If Array and ICollection are empty, the number of elements contained in the objects is 0.
IsAssignableTo <TargetType>-you can check whether the specified object can be converted to an instance of the TargetType.
GreaterThan <T>/LessThan <T>/GreaterThanOrEqual <T>/LessThanOrEqual <T>-as the name suggests, this set of Strategies can be used to check for greater than or less

These classes do not need or need to be explicitly instantiated (the constructor of the built-in implementation class is private and cannot be called directly). You only need to use static members of the Check class for access:

For example:

Check. NotNull
Check. NotNullOrEmpty
Check. IsAssignableTo <TargetType> ()
Check. GreaterThan <T> (T compareValue)
Check. LessThan <T> (T compareValue)
Check. GreaterThanOrEqual <T> (T compareValue)
Check. LessThanOrEqual <T> (T compareValue)

At the same time, this ultimate version also adds a reload like the following for the Require and Ensure methods of Check:

Public static void Require (object obj, string objName, params ICheckStrategy [] strategies)

The first parameter of this overload is the object to be checked, and the second parameter represents the description name of the object to be checked (not necessarily the variable or parameter name, the third parameter is a set of variable numbers of ICheckStategy instances.

Examples (For more examples, refer to the test project in the source code of this article ):

1 private static void RequireStrategy (TestClass obj, object objs, object objList)
2 {
3 Check. Require (obj, "obj", Check. NotNull );
4 Check. Require (objs, "objs", Check. NotNull, Check. IsAssignableTo <Array> (), Check. NotNullOrEmpty );
5 Check. Require (objList, "objList", Check. NotNull, Check. IsAssignableTo <ICollection> (), Check. NotNullOrEmpty );
6}

In the sample code, the RequireStategy method can be checked but not necessarily of a strong type.

For the most common NotNull detection, such as Check. require (obj, "obj", Check. notNull), Check. notNull can be left unspecified, that is, Check. require (obj, "obj") is equivalent to explicitly specifying Check. notNull.

Check. the last set of parameters for this overload of Require () is a set of Check Stategies. When multiple parameters are specified, their Pass methods will be called in sequence. If a Pass request returns false, the subsequent check is terminated, and the prompt information only contains the first Stategy error message that is passable.

The call of the second and third Require () methods in the above sample code is equivalent to checking the type and whether the array or set object is not empty (the number of elements is 0 ). The NotNullOrEmpty Strategy can also be used to check the string type. For non-string, Array, or ICollection types, the Pass method always returns false.

Similarly, the sample code for using Strategies such as GreaterThan is as follows:

1 private static void CompareArguments (int x, int y, double z)
2 {
3 Check. Require (x, "x", Check. GreaterThan <int> (0 ));
4 Check. Require (y, "y", Check. LessThanOrEqual <int> (0 ));
5 Check. Require (z, "z", Check. GreaterThanOrEqual <double> (0.1 ));
6}

We can also use Check. require (x, "x", Check. greaterThan <int> (0), Check. syntax such as LessThanOrEqual <int> (10) checks whether x is 0 <x <= 10.

You may want to ask how to use a syntax such as StrategyCheck. Require (obj! = Null, "obj cocould not be null.") What are the advantages of this syntax?

The biggest advantage is that you do not have to specify the description of the error that is repeated over and over again for common check types, such as "obj cocould not be null.", which can contain many letters. In addition, the Strategy makes it flexible and convenient to encapsulate and expand common inspection logic. We can easily inherit the ICheckStrategy interface and extend our own query logic.

As mentioned above, all default error description message templates are defined in # region Const Literals of the Check class. We can modify the default prompt message as needed. Of course, for most applications, the default English prompt message is enough. The following lists some common error messages after the Strategy check fails when an exception is thrown by default:

Check. NotNull-Test method DesignByContract. UnitTests. TestPreconditionNull threw exception: DesignByContract. PreconditionException: obj cocould not be null.

Check. NotNullOrEmpty-Test method DesignByContract. UnitTests. TestPreconditionStrategyCollectionEmpty threw exception: DesignByContract. PreconditionException: objList cocould not be null or empty.

Check. IsAssignableTo <ICollection> ()-Test method DesignByContract. UnitTests. TestPreconditionStrategyCollectionNotIsAssignableFrom threw exception: DesignByContract. PreconditionException: objList is not assignable to System. Collections. ICollection.

Check. GreaterThanOrEqual <double> (0.1)-Test method DesignByContract. UnitTests. TestCompareDoubleGreaterThanOrEqual threw exception: DesignByContract. PreconditionException: obj must be >=0.1.

Last Updated: 2007/10/5

// The End

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.