Tuesday, 2 October 2012

Injecting dependencies into SignalR hub using Unity

In one of my earlier post, I discussed on Dependency Injection with SignalR using Ninject. In this post, we will see how to do it with Unity.

We had a NuGet package available to make our work easier to work with Ninject. We don’t have such a package for Unity. The only difference is that, we need to write one more small class to make the things work.

We need to define a dependency resolver that derives from SignalR.DefaultDependencyProvider and override the methods GetService and GetServices. This implementation is shown below:

public class UnityDependencyResolver : DefaultDependencyResolver
{
        IUnityContainer container;
 
        public UnityDependencyResolver(IUnityContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container", "Containet cannot be null");
            }
            this.container = container;
        }
 
        public override object GetService(Type serviceType)
        {
            return base.GetService(serviceType) ?? container.Resolve(serviceType);
        }
 
        public override IEnumerable<object> GetServices(Type serviceType)
        {
            return base.GetServices(serviceType) ?? container.ResolveAll(serviceType);
        }
}

We have to register the requested types and target types to the container as shown below:
public static class UnityIoC
{
    public static IUnityContainer Initialize()
    {
        IUnityContainer container = new UnityContainer();
        container.RegisterType<ICustomerRepository, CustomerRepository>();
        container.RegisterType<IJavaScriptMinifier, NullJavaScriptMinifier>();
        return container;
    }
}

In this case, I registered the target type for IJavaScriptMinifier as Unity fails to work without this registration. Ninject and StructureMap don’t need this type to be registered. As last step, we need to set the resolver to RouteTable.Route.MapHubs when the application starts.
public class Global : System.Web.HttpApplication
{ 
    void Application_Start(object sender, EventArgs e)
    {
        GlobalHost.DependencyResolver = new UnityDependencyResolver(UnityIoC.Initialize());
        RouteTable.Routes.MapHubs();            
    }
}

Important note: If you are using SignalR in an ASP.NET MVC project, then configure SignalR first and then ASP.NET MVC. Check SignalR wiki for more details.

Happy Coding!

3 comments:

  1. This doesn't work for MVC4 applications, it will throw the exceptions:

    The type Website1.UnityDependencyResolver does not appear to implement Microsoft.Practices.ServiceLocation.IServiceLocator.
    Parameter name: commonServiceLocator

    ReplyDelete
    Replies
    1. Rogier,

      I saw many significant changes done on SignalR's latest RC release. I will update all the posts once the final version is released. I would like to know if you are still facing the issue you mentioned. If so, please send me some more details using Contact Me link above. I will reply you at the earliest.

      Delete
  2. Rogier,

    Thanks for pointing. I will check this out and update the post. I am on vacation now, so I need some time.

    ReplyDelete