Questions D'Injection De Dépendance SignalR +

J'utilise SignalR dans mon application MVC3, et puisque j'ai implémenté L'Injection de dépendance StructureMap sur mes contrôleurs, je voudrais faire la même chose dans mon hub, mais je n'arrive pas à le faire fonctionner.

Dites-moi ce qui ne va pas avec mes codes ci-dessous:

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>();
    }
}

Cio.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);
    }
}

Merci

22
demandé sur Leniel Maccaferri 2012-03-20 20:04:22

4 réponses

Obtenir Structuremap dans SignalR est en fait assez facile. Vous voulez d'abord créer votre propre résolveur:

Résolveur StructureMap

Usage:

using SignalR.Infrastructure;
using StructureMap;

Classe:

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));
    }
}

L'idée ici est d'essayer d'utiliser votre conteneur pour résoudre les dépendances, si vous n'avez pas la dépendance câblée, passez-la au résolveur par défaut. De cette façon, vous n'avez pas à vous soucier de toutes les autres dépendances dans SignalR et ne pouvez vous concentrer que sur les choses dans lesquelles vous voulez injecter (Hubs, ConnectionIdFactory, MessageBus, etc.).

Liaisons pour le résolveur et le concentrateur

Ensuite, vous voulez l'inscrire dans votre conteneur (j'aime utiliser des registres):

Usage:

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

Classe:

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

Remplacement Du Résolveur

Enfin, vous voudrez dire à SignalR d'utiliser votre résolveur au lieu de la valeur par défaut:

Global::Application_Start ou WebActivator:: Pre_Start

Usage:

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

Vous avez besoin de plus D'informations?]}

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

Hub stupide avec des dépendances injectées

Maintenant, vous pouvez simplement Injecter toutes les dépendances que votre conteneur connaît dans les hubs eux-mêmes:

[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)); });
    }
}

8
répondu Gary.S 2012-12-11 09:57:43

Avez-vous suivi les instructions ici:- https://github.com/SignalR/SignalR/wiki/Extensibility ?

Vous devrez utiliser AspNetHost.SetResolver.

5
répondu Ian Mercer 2012-03-23 05:22:44

Je sais que c'est un vieux fil, mais pour ceux qui se demandent Où est L'AspNetHost.SetResolver dans la nouvelle version de signalR, vous pouvez l'utiliser dans la structure App_startemapmvc.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);
    }
2
répondu CloneXpert 2013-06-12 07:48:01

Ajoutez quelque chose comme ceci à un fichier dans votre dossier App_Start. Cet extrait de code est pour Ninject, il suffit donc de remplacer 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>();
        }
    }
}
1
répondu Turp 2012-03-25 18:31:05