private override

11Dec/089

static reflection – Method Guards

Another bit of magic with static reflection. Refer to my last post for a little more explanation of static reflection, and a sweet implementation (IMO) of INotifyPropertyChanged using static reflection.

In the past several years, on several projects, I've seen many lines of code at the beginning of public interface methods that look like:

    public class WebServer
    {
        public void BootstrapServer(int port, string rootDirectory, string serverName)
        {
            if( rootDirectory == null )
            {
                throw new ArgumentNullException( "rootDirectory" );
            }
            if( serverName == null )
            {
                throw new ArgumentNullException( "serverName" );
            }

            // Bootstrap the server
        }
    }

I realize the need, since we don't have real DbC in .NET (yet), but I REALLY dislike this and feel it to be a pretty bad smell.  It feels unDRY, obscures essence, and I just plain don't like it. ;)

So, here is an implementation that makes it tolerable, if not enjoyable (because of the coolness of using static reflection), because I think it actually adds to the essence and overall readability of a given method.

This is what the above code can now look like:

    public class WebServer
    {
        public void BootstrapServer( int port, string rootDirectory, string serverName )
        {
            Guard.IsNotNull( () => rootDirectory );
            Guard.IsNotNull( () => serverName );

            // Bootstrap the server
        }
    }

And here is the implementation:

    public static class Guard
    {
        public static void IsNotNull<T>(Expression<Func<T>> expr)
        {
            // expression value != default of T
            if (!expr.Compile()().Equals(default(T)))
                return;

            var param = (MemberExpression) expr.Body;
            throw new ArgumentNullException(param.Member.Name);
        }
    }

Lovin it!  Hope you do too.

Comments (9) Trackbacks (2)
  1. !expr.Compile()().Equals(default(T))

    yuck.

    Why not just have a static “Validator” class?

    validator.IsNotNull(rootDirectory);

    impl:

    public class Validator
    {
    public void IsNotNull(T item)
    {
    if(item == null) throw new ArgumentNullException(item);
    }
    }

    also:

    if (!expr.Compile()().Equals(default(T)))
    return;

    is something of a code smell in itself.

  2. While I agree that nasty compile statement is a bit smelly, its only in your guard class, and not sprinkled throughout your application code.

    Also, while there is something to be said for the simplicity of your Validator class, it doesn’t solve the issue I’m after. Your “throw new ArgumentNullException(item);” gives no context as to which argument was null. In fact, the thing you’re passing into that constructor, is null itself (which will be less than helpful when debugging/testing). My solution provides you with the parameter name (which is what that constructor argument is supposed to be anyways, not the actual value, which in this case is always null, by definition).

    Thanks for the feedback!

  3. Good point well made! I apologise for the tone of my comment – rereading it, it is much more aggressive than I intended! Thanks for your interesting response.

    Cheers,

    xan

  4. Well played with the Guard Method. Do you take a performance hit each time the method is executed do to the expression needing to figure out the Name of the member? Is there a significant change in performance between passing in the name and the value? Very clever :) !

  5. You should check out the Lokad shared libraries. They use Func and some IL digging instead of Expression<Func>. So it doesn’t require the extra compilation to evaluation the argument.

    Here’s the post explaining how it works: http://abdullin.com/journal/2008/12/19/how-to-get-parameter-name-and-argument-value-from-c-lambda-v.html

  6. I find this concept interesting, and wonder if it can be taken one step further. Instead of passing in a lambda of the parameter, is there a way to pass in a reference to the current function’s param array, and validate them?

  7. That is a great idea, but I don’t think you have access to that level of meta information in C#. Please correct me if I’m wrong (anyone).

    This is sort of doing something similar to what you said though. You’re not actually passing in a lambda (although it does indeed look like one)… in reality you’re passing an Expression (just a piece of code) that gets analyzed and validated inside the validator.

  8. Excellent work getting this far however I did note that one failing was when calling Guard.IsNull with a string with a value of null it throws a NullReferenceException because of the fact that the default value T is String.Empty.

    One way to handle this scenario would be to use reflection and Reflect on expr.Compile().Target.Globals[0].Value which happens to contain information on the given expression including the argument name, value and type however this does seem to defeat the whole purpose.

    Example test code that produces the above results:

    [Test]
    public void ShouldThrowArgumentNullExceptionWhenGivenStringWithNullValue()
    {
    const string rootDirectory = null;
    const string serverName = null;
    var server = new WebServer();

    TestUtilities.Assert.ThrowsExactly(
    () => server.BootstrapServer(0, rootDirectory, serverName));
    }


Leave a comment