Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SignalR + Dependency Injection Questions

Tags:

I am using SignalR in my MVC3 application, and since I have implemented StructureMap Dependency Injection on my controllers I would like to do the same in my hub, but I can't seem to get it working.

Please tell me what's wrong with my codes below:

SignalRSmDependencyResolver.cs

public class SignalRSmDependencyResolver : DefaultDependencyResolver {     private IContainer _container;      public SignalRSmDependencyResolver(IContainer container)     {         _container = container;     }      public override object GetService(Type serviceType)     {         object service = null;         if (!serviceType.IsAbstract && !serviceType.IsInterface && serviceType.IsClass)         {             // Concrete type resolution             service = _container.GetInstance(serviceType);         }         else         {             // Other type resolution with base fallback             service = _container.TryGetInstance(serviceType) ?? base.GetService(serviceType);         }         return service;     }      public override IEnumerable<object> GetServices(Type serviceType)     {         var objects = _container.GetAllInstances(serviceType).Cast<object>();         objects.Concat(base.GetServices(serviceType));         return objects;     } } 

SignalRExtensionsRegistry.cs

public class SignalRExtensionsRegistry : Registry {     public SignalRExtensionsRegistry()     {         For<IDependencyResolver>().Add<SignalRSmDependencyResolver>();     } } 

IoC.cs

public static class IoC {     public static IContainer Initialize() {          var container = BootStrapper.Initialize();          container.Configure(x =>         {             x.For<IControllerActivator>().Singleton().Use<StructureMapControllerActivator>();         });          return container;     } }  public class StructureMapControllerActivator : IControllerActivator {     public StructureMapControllerActivator(IContainer container) {         _container = container;     }      private IContainer _container;      public IController Create(RequestContext requestContext, Type controllerType) {         IController controller = DependencyResolver.Current.GetService(controllerType) as IController;         return controller;     } } 

AppStart_Structuremap.cs

[assembly: WebActivator.PreApplicationStartMethod(typeof(StoreUI.AppStart_Structuremap), "Start")]  namespace MyNameSpace { public static class AppStart_Structuremap {     public static void Start() {         var container = (IContainer) IoC.Initialize();         DependencyResolver.SetResolver(new StructureMapDependenceyResolver(container));         AspNetHost.SetResolver(new StructureMapDependencyResolver(container));                 } } } 

NotificationsHub.cs

[HubName("notificationsHub")] public class NotificationsHub : Hub {         #region Declarations     private readonly IUserService userService;     #endregion      #region Constructor      public NotificationsHub(IUserService userService)     {         this.userService = userService;     }      #endregion      public void updateServer(string message)     {         Clients.updateClient(message);     } } 

Thanks

like image 329
dmc Avatar asked Mar 20 '12 16:03

dmc


People also ask

How long do SignalR connections stay open?

The default keepalive timeout period is currently 20 seconds. If your client code tries to call a Hub method while SignalR is in reconnecting mode, SignalR will try to send the command. Most of the time, such attempts will fail, but in some circumstances they might succeed.

Is SignalR bidirectional?

ASP.NET SignalR is a new library for ASP.NET developers that makes developing real-time web functionality easy. SignalR allows bi-directional communication between server and client. Servers can now push content to connected clients instantly as it becomes available.

Does SignalR require IIS?

IIS 8 or IIS 8 Express should be used for SignalR to use Web Socket and the server must be using Windows 8, Windows Server 2012 or later and the Web Socket must be enabled for the IIS.


1 Answers

Getting Structuremap into SignalR is actually pretty easy. First you want to create your own resolver:

StructureMap Resolver

Usings:

using SignalR.Infrastructure; using StructureMap; 

Class:

public class StructureMapResolver : DefaultDependencyResolver {     private IContainer _container;      public StructureMapResolver(IContainer container)     {         _container = container;     }      public override object GetService(Type serviceType)     {         object service = null;         if (!serviceType.IsAbstract && !serviceType.IsInterface && serviceType.IsClass)         {             // Concrete type resolution             service = _container.GetInstance(serviceType);         }         else         {             // Other type resolution with base fallback             service = _container.TryGetInstance(serviceType) ?? base.GetService(serviceType);         }         return service;     }      public override IEnumerable<object> GetServices(Type serviceType)     {         var objects = _container.GetAllInstances(serviceType).Cast<object>();         return objects.Concat(base.GetServices(serviceType));     } } 

The idea here is to try and use your container to resolve the dependencies, if you do not have the dependency wired up, pass it through to the default resolver. This way you don't have to worry about all of the other dependencies in SignalR and can focus only on the stuff you want to inject into (Hubs, ConnectionIdFactory, MessageBus, etc.).

Bindings for Resolver and Hub

Next you will want to register this in your container (i like using registries):

Usings:

using SignalR.Infrastructure; using StructureMap.Configuration.DSL; 

Class:

public class ExtensionsRegistry : Registry {     public ExtensionsRegistry()     {         For<IDependencyResolver>().Add<StructureMapResolver>();     } } 

Resolver Replacement

Finally you will want to tell SignalR to use your resolver instead of the default:

Global::Application_Start or WebActivator::Pre_Start

Usings:

using SignalR.Hosting.AspNet; using SignalR.Infrastructure; 

Application_Start:

// Make sure you build up the container first AspNetHost.SetResolver(StructureMap.ObjectFactory.GetInstance<IDependencyResolver>()); 

Silly Hub with injected dependencies

Now you can just inject any dependencies your container knows about into the hubs themselves:

[HubName("defaultHub")] public class DefaultHub : Hub, IDisconnect {     private readonly IRepository _repo;     public DefaultHub(IRepository repo)     {         _repo = repo;     }      public void Connect()     {         Caller.setUser(Context.ConnectionId);         Clients.addMessage(string.Format("{0} has connected", Context.ConnectionId));     }      public void MessageSender(string message)     {         Caller.addMessage(_repo.RepositoryMessage());         Clients.addMessage(message);     }      public Task Disconnect()     {         var clientId = this.Context.ConnectionId;         return Task.Factory.StartNew(() => { Clients.addMessage(string.Format("{0} has disconnected", clientId)); });     } } 
like image 178
Gary.S Avatar answered Sep 21 '22 18:09

Gary.S