Register | Login

Stacking Code

public interface IBlog { string Dump(Stream consciousness); }

IDependencyResolver and Generics

Wednesday, 2 February, 2011 @ 8:05 PM < Adam Boddington
Tags: ASP.NET MVC, Inversion of Control

If you've been paying attention to the chatter around ASP.NET MVC 3 you'll know the extensibility in MVC 3 is handled through a dependency resolver. It's not another IOC container but rather an adapter to whatever IOC container you're already comfortable with. There are two methods that need to be hooked up.

public interface IDependencyResolver
{
    object GetService(Type serviceType);
    IEnumerable<object> GetServices(Type serviceType);
}

If you're using one of the more common IOC containers in the .NET space, you're probably already covered. Most already have implementations of IDependencyResolver available through NuGet or on various blogs. However, if you've rolled your own IOC container, or, like me, already use a custom IOC adapter (more here), you'll probably have to implement IDependencyResolver yourself.

The Problem

If your custom IOC container or adapter only has generic methods, here's where you might run into a little bit of trouble.

public class MyDependencyResolver : IDependencyResolver
{
    public object GetService(Type serviceType)
    {
        // Most containers throw an exception if the service
        // type can't be found. GetService expects a null.
        if (!GetServices(serviceType).Any())
            return null;

        return MyContainer.MyGet< // um...
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return MyContainer.MyGetAll< // oh crap
    }
}

It's not immediately obvious how to take a type and call a generic method with it, at least it wasn't to me. It's easy to take a generic type parameter and convert that into a type with typeof, but I was surprised to realise I had never gone the other way, at least not in recent memory. Luckily someone was at hand who knew how to do it. Many thanks to Angus Douglas.

The Solution

Here it is using reflection with GetMethod and MakeGenericMethod.

public class MyDependencyResolver : IDependencyResolver
{
    public MyDependencyResolver()
    {
        // The types are only needed if the MyGet method is overloaded.
        MyGetMethod = typeof(MyContainer).GetMethod("MyGet", new Type[0]);
        // The types are only needed if the MyGetAll method is overloaded.
        MyGetAllMethod = typeof(MyContainer).GetMethod("MyGetAll", new Type[0]);
    }

    private MethodInfo MyGetMethod { get; set; }
    private MethodInfo MyGetAllMethod { get; set; }

    public object GetService(Type serviceType)
    {
        // Most containers throw an exception if the service
        // type can't be found. GetService expects a null.
        if (!GetServices(serviceType).Any())
            return null;

        MethodInfo myGetMethod = MyGetMethod.MakeGenericMethod(new[] { serviceType });

        return myGetMethod.Invoke(null, null);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        MethodInfo myGetAllMethod = MyGetAllMethod.MakeGenericMethod(new[] { serviceType });

        return (IEnumerable<object>)myGetAllMethod.Invoke(null, null);
    }
}

For completeness, all that remains is hooking up the dependency resolver in Global.asax.cs.

protected void Application_Start()
{
    // Inversion of Control / Dependency Injection
    // Insert custom IOC container/adapter initialisation here.
    MyContainer.MyGet<IKernel>().Load(new MyNinjectModule());
    // Hook up MyDependencyResolver.
    DependencyResolver.SetResolver(new MyDependencyResolver());

    // MVC Plumbing
    AreaRegistration.RegisterAllAreas();
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

There are 0 comments.


Comments

Leave a Comment

Please register or login to leave a comment.


Older
Better Living Through Chemistry

Newer
Running a Mercurial Server on IIS 7.5

Older
Better Living Through Chemistry

Newer
Running a Mercurial Server on IIS 7.5

browse with Pivot


About


Projects

Building Neno


RSS
Recent Posts

Codility Nitrogenium Challenge
OS X Lock
HACT '13
Codility Challenges
Priority Queue


Tags

Architecture (13)
ASP.NET (2)
ASP.NET MVC (13)
Brisbane Flood (1)
Building Neno (38)
C# (4)
Challenges (3)
Collections (1)
Communicator (1)
Concurrency Control (2)
Configuration (1)
CSS (5)
DataAnnotations (2)
Database (1)
DotNetOpenAuth (2)
Entity Framework (1)
FluentNHibernate (2)
Inversion of Control (5)
JavaScript (1)
jQuery (4)
Kata (2)
Linq (7)
Markdown (4)
Mercurial (5)
NHibernate (20)
Ninject (2)
OpenID (3)
OS X (1)
Pivot (6)
PowerShell (8)
Prettify (2)
RSS (1)
Spring (3)
SQL Server (5)
T-SQL (2)
Validation (2)
Vim (1)
Visual Studio (2)
Windows Forms (3)
Windows Service (1)


Archives


Powered by Neno, ASP.NET MVC, NHibernate, and small furry mammals. Copyright 2010 - 2011 Adam Boddington.
Version 1.0 Alpha (d9e7e4b68c07), Build Date Sunday, 30 January, 2011 @ 11:37 AM