Tuesday 18 December 2012

MongoDB Developer Course Success

A bit off topic today, just some good news. In an earlier post, I mentioned that I was on a MongoDB developer course (ran by 10gen, the MongoDB company). Last week was the final week of the course with the final exam deadline this Monday. The results have just been published - I received a grade of 85% so have officially passed the course (certificates are awarded from 65% onwards).

The course has given me an excellent grounding in MongoDB and I just wanted to thank 10gen for administrating it. It looks like they are running a Java version of the course next year, so I highly recommend any developers interested in MongoDB to enrol onto it.

It's a nice way to end a busy year. Merry Christmas and Happy New Year.

Tuesday 4 December 2012

Dynamic Typing and Extension Methods

Earlier today I came across an interesting runtime exception of type RuntimeBinderException. The specific exception message was:

'System.DateTime' does not contain a definition for 'ToUKFormat'

'ToUKFormat' is a custom extension method on DateTime that I wrote and was in-scope at compile time when I called it. So what caused the runtime exception? It turns out that you cannot call an extension method on an object/value that is dynamically typed. In my case, I was using the dynamic ViewBag in an ASP.NET MVC application to store a DateTime value - then in my view, I was retrieving that value from the ViewBag and calling a custom written extension method on it ('ToUKFormat'). In razor syntax, I was doing something similar to:

@ViewBag.Foo.Bar.ToUKFormat()
I have given the solution further below but if you want to reproduce the problem in a simple console application, you can use the following code:

namespace DynamicRuntimeIssue
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic today = DateTime.Today;

            Console.WriteLine(today.ToUKFormat()); // Exception...
            Console.ReadLine();
        }
    }

    static class DateTimeExtensions
    {
        public static string ToUKFormat(this DateTime dateTime)
        {
            return dateTime.ToString("dd/MM/yyyy");
        }
    }
}
When you run the code above, you will encounter the aforementioned exception. Of course, if you appropriately type the 'today' variable to a DateTime rather than dynamic, then you'll find that it all works as expected. However, if you cannot avoid the use of dynamic, like for example in my case where I was using ViewBag - then you can overcome this exception by calling your extension method as if it was any normal static method. You call the method and pass-in your object/value through as an actual parameter. Following on from the example above, you would therefore have:

Console.WriteLine(DateTimeExtensions.ToUKFormat(today));
Rather than:

Console.WriteLine(today.ToUKFormat());
If you want to understand why you can't call extension methods on a dynamic type, then go over to this stackoverflow question where someone else has had the same issue - you will particularly want to read Eric Lippert's response dated March 15 2011.