Feb 122011
 

 

In this blog post I am presenting a simple validation framework that you can reuse in your code. Also I will be putting here two code snippets that will make it easier for you to add preconditions to your code.

When Visual Studio 2010 was first realeased, one of the features that I expected the most was code contracts. Unfortunately after including them in one of my large projects, it became more clear that at this moment it is not mature enough to be used. Build time increases rapidly when having a lot of source code files and using the code contracts. Enabling static contract validation is even worse, almost doubling the build time on an average development machine.

All that being said, I really like the code contracts way of specifying preconditions. Most of the time I don’t use post-conditions, but being able to specify validation criteria means that the code will be more robust.

For simplicity this example here will only cover the Requires method, but it can easily be extended to provide most other methods from the System.Diagnostics.Contracts.Contract class.

What we want is to be able to specify preconditions like in the following snippet:

public void SomeMethod(string argument)
{
	Contract.Requires<ArgumentNullException>(argument != null, "Argument must not be null");
	Contract.Requires<ArgumentException>(argument != string.Empty, "Argument must not be empty string");
	Contract.Requires<InvalidOperationException>(false, "Message format: {0}", argument);
}

The above method will throw an ArgumentNullException if the supplied argument is null, an ArgumentException if the supplied argument is an empty string or an InvalidOperationException. The third precondition demonstrates the ability to specify a message format and multiple arguments (similar to the String.Format method).

Since the Requires method will receive a generic exception type argument, we don’t know if the exception constructor can receive a string argument, so our implementation must rely on reflection to create an instance of the exception. Since I am a big fan of expressions, the implementation is not a “brute-force” reflection invocation of the constructor, but instead I will be creating a lambda expression that can be reused.

The first time our Requires method is called, we can create a lambda expression that will instantiate the exception type. This expression can be cached and subsequent calls to Requires with the same exception type will invoke the cached lambda expression to create a new instance of the type:

using System;
using System.Linq.Expressions;

public static class Contract
{
    private static class ContractException<TException>
    {
        private static Func<TException> defaultConstructorExpression;
        private static Func<string, TException> messageConstructorExpression;

        public static Func<TException> New
        {
            get
            {
                if (defaultConstructorExpression == null)
                {
                    InitializeDefaultConstructorExpression();
                }

                return defaultConstructorExpression;
            }
        }

        public static Func<string, TException> NewWithMessage
        {
            get
            {
                if (messageConstructorExpression == null)
                {
                    InitializeMessageConstructorExpression();
                }

                return messageConstructorExpression;
            }
        }

        private static void InitializeDefaultConstructorExpression()
        {
            var newExpression = Expression.New(typeof(TException));
            defaultConstructorExpression = Expression.Lambda<Func<TException>>(newExpression).Compile();
        }

        private static void InitializeMessageConstructorExpression()
        {
            var constructorInfo = typeof(TException).GetConstructor(new[] { typeof(string) });
            if (constructorInfo == null)
            {
                messageConstructorExpression = msg => New();
                return;
            }

            var parameterExpression = Expression.Parameter(typeof(string));
            var newExpression = Expression.New(constructorInfo, parameterExpression);
            messageConstructorExpression = Expression.Lambda<Func<string, TException>>(newExpression, parameterExpression).Compile();
        }
    }

    public static void Requires<TException>(bool condition) where TException : Exception
    {
        if (!condition)
        {
            throw ContractException<TException>.New();
        }
    }

    public static void Requires<TException>(bool condition, string message) where TException : Exception
    {
        if (!condition)
        {

            throw ContractException<TException>.NewWithMessage(message);
        }
    }

    public static void Requires<TException>(bool condition, string messageFormat, params object[] args) where TException : Exception
    {
        if (!condition)
        {
            var message = string.Format(messageFormat, args);
            Requires<TException>(condition, message);
        }
    }
}

Below you can find the Contract class code, as well as two code snippets. These snippets must be copied to My DocumentsVisual Studio 2010Code SnippetsVisual C#My Code Snippets. The shortcuts for the snippets are:

  • cre –> will create a generic Contract.Requires statement
  • cren –> will create a Contract.Requires<ArgumentNullException> statement

These snippets have actually the same shortcut as the ones included in the Code Contracts extension required for the .NET framework built-in contracts. If you already have that extension installed, you don’t need the snippets.

Download the files here: 

 Simple reusable validation framework