SignalR + Dependency Injection Questions

前端 未结 4 1253
醉酒成梦
醉酒成梦 2020-12-29 23:47

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\

相关标签:
4条回答
  • 2020-12-30 00:19

    I know this is an old thread, but for those who are wondering where is the AspNetHost.SetResolver in the newer version of signalR, you can use this in the App_Start StructuremapMvc.cs:

        public static void Start() {
            IContainer container = IoC.Initialize();
            GlobalHost.DependencyResolver = new SignalRSmDependencyResolver(container); // for signalR
    
            DependencyResolver.SetResolver(new StructureMapDependencyResolver(container));
            GlobalConfiguration.Configuration.DependencyResolver = new StructureMapDependencyResolver(container);
        }
    
    0 讨论(0)
  • 2020-12-30 00:20

    Have you followed the instructions here:- https://github.com/SignalR/SignalR/wiki/Extensibility ?

    You'll need to use AspNetHost.SetResolver.

    0 讨论(0)
  • 2020-12-30 00:32

    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)); });
        }
    }
    
    0 讨论(0)
  • 2020-12-30 00:32

    Add something like this to a file in your App_Start folder. This code snippet is for Ninject, so just replace AspNetHost.SetResolver()

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;
    using Ninject;
    using SignalR.Hosting.AspNet;
    using SignalR.Infrastructure;
    using SignalR.Ninject;
    using Web.Models;
    
    [assembly: WebActivator.PreApplicationStartMethod(typeof(Web.App_Start.NinjectSignalR), "Start")]
    
    namespace Web.App_Start
    {
        public static class NinjectSignalR
        {
            public static void Start()
            {
                IKernel kernel = CreateKernel();
                // switch this line to the structuremap resolver
                AspNetHost.SetResolver(new NinjectDependencyResolver(kernel));
            }
    
            private static IKernel CreateKernel()
            {
                var kernel = new StandardKernel();
                RegisterServices(kernel);
                return kernel;
            }
    
            private static void RegisterServices(IKernel kernel)
            {
                // add your services here
                //kernel.Bind<IRepository>().To<Repository>();
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题