Using SignalR with Unity

This post demonstrates how to use Unity as an IoC for SignalR. To inject into SignalR, the Microsoft.AspNet.SignalR.Hubs.IHubActivator class should be used.

Code: https://github.com/damienbod/SignalRHostWithUnity

Step 1:
Use NuGet to add Unity and SignalR

SignalRUnity1

and also SignalR Self Host
SignalRUnity2

Step 2:
Create an UnityHubActivator class.

This class implements the IHubActivator interface. The Unity container is used in the public IHub Create(HubDescriptor descriptor) method.

using System;
using Microsoft.AspNet.SignalR.Hubs;
using Microsoft.Practices.Unity;

namespace SignalRHostWithUnity.Unity
{
    public class UnityHubActivator : IHubActivator
    {
        private readonly IUnityContainer _container;

        public UnityHubActivator(IUnityContainer container)
        {
            _container = container;
        }

        public IHub Create(HubDescriptor descriptor)
        {
            if (descriptor == null)
            {
                throw new ArgumentNullException("descriptor");
            }

            if (descriptor.HubType == null)
            {
                return null;
            }

            object hub = _container.Resolve(descriptor.HubType) ?? Activator.CreateInstance(descriptor.HubType);
            return hub as IHub;
        }
    }
}

Step 3:
Create an UnityConfiguration class and register your Hub class. Important is the IHubActivator registry:

using System;
using Microsoft.AspNet.SignalR.Hubs;
using Microsoft.Practices.Unity;
using SignalRHostWithUnity.DataAccess;

namespace SignalRHostWithUnity.Unity
{
    public class UnityConfiguration
    {
        #region Unity Container
        private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
        {
            var container = new UnityContainer();
            RegisterTypes(container);
            return container;
        });

        public static IUnityContainer GetConfiguredContainer()
        {
            return container.Value;
        }
        #endregion

        public static void RegisterTypes(IUnityContainer container)
        {
            container.RegisterType<MyHub, MyHub>(new ContainerControlledLifetimeManager());
            container.RegisterType<IHubActivator, UnityHubActivator>(new ContainerControlledLifetimeManager());
            container.RegisterType<IRepositoryUnityTestClass, RepositoryUnityTestClass>();
            
        }
    }
}

Now the Hub class can use constructor injection.

public class MyHub : Hub
    {
        private readonly IRepositoryUnityTestClass _repositoryUnityTestClass;

        public MyHub(IRepositoryUnityTestClass repositoryUnityTestClass)
        {
            _repositoryUnityTestClass = repositoryUnityTestClass;
        }

        public void AddMessage(string name, string message)
        {
            Console.WriteLine("Hub AddMessage {0} {1}\n", name, _repositoryUnityTestClass.SayHello() + message);
            Clients.All.addMessage(name, _repositoryUnityTestClass.SayHello() + message);
        }

Step 4:
Register your UnityHubActivator class to the GlobalHost.DependencyResolver

using System;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using Microsoft.Owin;
using Microsoft.Owin.Hosting;
using SignalRHostWithUnity.Dto;
using SignalRHostWithUnity.Unity;

namespace SignalRHostWithUnity
{
    class Program
    {
	    private static  IHubContext _hubContext;

        static void Main(string[] args)
        {
		    GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => new UnityHubActivator(UnityConfiguration.GetConfiguredContainer()));

            string url = "http://localhost:8089";
					
            using (WebApp.Start(url))
            {
			    _hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();

                Console.WriteLine("Server running on {0}", url);
				
                while (true)
                {
                    string key = Console.ReadLine();
                    if (key.ToUpper() == "W")
                    {
                        _hubContext.Clients.All.addMessage("server", "ServerMessage");
                        Console.WriteLine("Server Sending addMessage\n");
                    }
                    if (key.ToUpper() == "E")
                    {
                        _hubContext.Clients.All.heartbeat();
                        Console.WriteLine("Server Sending heartbeat\n");
                    }
                    if (key.ToUpper() == "R")
                    {
                        var helloModel = new HelloModel {Age = 37, Molly = "pushed direct from Server "};
                        _hubContext.Clients.All.sendHelloObject(helloModel);
                        Console.WriteLine("Server Sending sendHelloObject\n");
                    }
                    if (key.ToUpper() == "C")
                    {
                        break;
                    }
                }

                Console.ReadLine();
            }
        }
    }
}

The Hub class is now resolved using unity and standard constructor injection can be used.

Links

http://yingtechthink.blogspot.kr/2014_01_01_archive.html

http://www.asp.net/signalr

http://unity.codeplex.com/

https://jabbr.net/#/rooms/signalr

4 comments

  1. Thanks for writing this post! I needed exactly this and it works great!

  2. This article was a great help to get this setup, thank you.

  3. Le Chinois · · Reply

    Thanks you so much, many tuto on internet didn’t work but yours is perfect !

    1. cheers thanks, greetings Damien

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: