Wednesday, March 11, 2009

Validate Parameters Using Attributes and PostSharp

I've been learning a lot about C# 4.0 lately and I have been very intrigued by the design by contract capabilities that will be added with the Microsoft Research Code Contracts project. One feature I'm particularly excited about is the static validation.

I've been working on a project which is little more than an abstract class and a bunch of test cases to verify that the outsourced implementers of this class make appropriate parameter validation on their overridden methods. I thought, "man, it sure would be nice if I could just put a code contract on my abstract class and then I wouldn't have to write all of these annoying unit tests."

Well, I just couldn't wait, so again I leveraged the pre-compiler flexibility of PostSharp and AoP concepts to simplify things a little (at least until code contracts are widely supported).

The first thing I did was define the contract for my parameter validation attributes:
[AttributeUsage(AttributeTargets.Parameter)]
public abstract class ParameterAttribute : Attribute
{
public abstract void CheckParameter(ParameterInfo parameter, object value);
}
Then, I wrote a method attribute with a method boundary aspect to process the parameter attributes:
[Serializable]
public class HasParameterAttributes : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
ParameterInfo[] pis = eventArgs.Method.GetParameters();
Object[] args = eventArgs.GetReadOnlyArgumentArray();

for (int i = 0; i < pis.Length; i++)
foreach (ParameterAttribute pa in pis[i].GetAttributes<ParameterAttribute>())
pa.CheckParameter(pis[i], args[i]);

base.OnEntry(eventArgs);
}
}
The version I wrote in honor of my friend Sir Nathan Rigsby is called CanHazParameterAttributes.

The HasParameterAttributes method attribute implementation uses an extension method I wrote to get a specific type of attributes from the PropertyInfo objects. You can find it in the article entitled: Extension Method to Get Custom Attributes with Reflection

I wrote two basic parameter validators to test the system:
public class NotNull : ParameterAttribute
{
public string Message { get; set; }
public override void CheckParameter(ParameterInfo parameter, object value)
{
if (value == null)
throw new ArgumentNullException(parameter.Name, Message);
}
}

public class NotEmpty : ParameterAttribute
{
public string Message { get; set; }

public override void CheckParameter(ParameterInfo parameter, object value)
{
if (value != null && value.ToString().Length == 0)
throw new ArgumentException(Message, parameter.Name);
}
}
The test I wrote does not execute like you would expect a unit test to execute. That is because I didn't have a lot of time to spend on this so I was too lazy to specify which test cases expect exceptions and which don't. If you run these test cases, you'll see that the ones which throw exceptions fail and the ones which don't throw exceptions pass. They perform as designed. Here's my NUnit test:
[TestFixture]
public class Tests
{
[Test, Combinatorial]
[HasParameterAttributes]
public void TestNotNull
([NotNull, Values(null, "", "Lulu")] string param1,
[NotEmpty, Values(null, "", "Lulu", 0)] object param2)
{ }
}

4 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Hi Patrick,

    Great article. It really got me thinking more carefully on how to solve all my validation woes. Was wondering if you had seen this post from the creator of PostSharp that kind of goes along the same lines (found here) and is to do with design by contract. Unfortunately the google code site for it is a mess but the correct place to find the source code is here.

    Ed

    ReplyDelete
  3. Nice!!
    one nice side effect is that it should be very easy (search and replace?!) to switch to MS CodeContracts when this becomes ready to use,
    which would offer you compile time checks for your input parameters.
    http://research.microsoft.com/en-us/projects/contracts/

    ReplyDelete
  4. Derby.js is a full-stack Model View Regulator structure that is generally utilized for most present day web applications. One of the extraordinary elements of this structure is its capacity to synchronize text information and JSON between data sets, servers, and programs continuously.
    Designers dealing with weighty front-end ventures will likewise see the value in the way that this structure upholds server-side delivering.
    Other incredible highlights of Derby.js incorporate compromise, formats restricting, and disconnected use, which makes composing multi-client applications a lot less difficult. As a designer, working involvement in this apparatus not just gives you a high ground over your rivals, it likewise assists you Node.js engineer with continuing stick out>> Mobilunity

    ReplyDelete