Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Unity IoC to register and resolve SignalR hubs

I think I'm missing something very simple and maybe just need a new set of eyes. I have an ASP.NET MVC application. In that app, I am using Unity for my IoC to handle dependency injection. Each of my repositories need to have a database factory injected into it and each database factory needs to have a principal injected into it. So far, I've been utilizing the PerRequestLifetimeManager to register these.

//Repositories

container.RegisterType<ChatMessageRepository>(new PerRequestLifetimeManager());
           container.RegisterType<SignalRConnectionRepository>(new PerRequestLifetimeManager());

//Context
container.RegisterType<IPrincipal, Principal>(new PerRequestLifetimeManager());
container.RegisterType<IDatabaseFactory, DatabaseFactory>(new PerRequestLifetimeManager());
container.RegisterType<UnitOfWork>(new PerRequestLifetimeManager());

Logically, I've tried to register my Hub in the same fashion.

container.RegisterType<ChatHub>(new PerRequestLifetimeManager()); 

However, whenever I run my app and navigate away from my chat page, I get a "Resolution of the dependency failed" exception and the InnerException tells me "Operation is not valid due to the current state of the object." I've also tried using the default (Transient), PerResolve, and ContainerControlled lifetime Unity managers when registering these guys and cannot seem to get resolve my issue.

Could someone just provide me some demo code with how you used Unity in an ASP.NET MVC application to handle dependency injection into your signalr hubs?

Here's where Unity will inject parameters into my SignalR Hub

public class ChatHub : Hub
{
    private readonly ChatMessageRepository _chatMessageRepository;
    private readonly SignalRConnectionRepository _signalRConnectionRepository;
    private readonly UnitOfWork _unitOfWork;

    public ChatHub(ChatMessageRepository chatMessageRepository,
        SignalRConnectionRepository signalRConnectionRepository,
        UnitOfWork unitOfWork)
    {
        _chatMessageRepository = chatMessageRepository;
        _signalRConnectionRepository = signalRConnectionRepository;
        _unitOfWork = unitOfWork;
    } ... }

Thanks!

like image 920
KWondra Avatar asked Jan 05 '14 02:01

KWondra


2 Answers

Do it in 3 steps

First. Create UnityHubActivator class

public class UnityHubActivator : IHubActivator
{
    private readonly IUnityContainer _container;

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

    public IHub Create(HubDescriptor descriptor)
    {
        return (IHub)_container.Resolve(descriptor.HubType);
    }
}

Second. Create Unity container and register your dependency resolver before run Startup class

unityContainer = new UnityContainer();
var unityHubActivator = new UnityHubActivator(_unityContainer);
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => unityHubActivator);
//register some types in container
WebApp.Start<Startup>(startOptions);

Third. Use it in your Hub

public class MyHub : Hub
{
    public MyHub(Logger logger)
    {
        logger.Info("hub constructor");
    }
}

Note. I do not change anything in my Startup class

like image 97
Marat Batalandabad Avatar answered Sep 21 '22 11:09

Marat Batalandabad


There's a trick to do that. You will need to do something like this:

container.RegisterType< ChatHub >(new InjectionFactory(CreateChatHub));

......

and then create a private method CreateChatHub

private static object CreateChatHub(IUnityContainer container)
{
    return new ChatHub();
}
like image 30
Gang Gao Avatar answered Sep 18 '22 11:09

Gang Gao