3

我最近升级到了优秀的 SignalR 库的新版本,并将我所有的依赖注入从 StructureMap 移到了 Ninject,因为 Ninject 似乎得到了更好的支持。

我已经使用此处描述的“从集线器外部通过集线器广播”的服务器端通知的依赖注入工作正常:https ://github.com/SignalR/SignalR/wiki/Hubs 。

我遇到的问题是来自 Javascript 集线器的所有 SignalR 消息似乎都没有触发依赖注入。

我也在使用 MVC4 WebAPI,它也需要一些努力才能使依赖注入工作。

这是我的集线器:

public class PresenceHub : Hub, IPresenceHub
{
    private readonly IUserRepository _userRepository;
    private readonly IFormsAuthenticationProvider _formsAuthenticationProvider;

    public PresenceHub(IFormsAuthenticationProvider formsAuthenticationProvider, IUserRepository userRepository)
    {
        _userRepository = userRepository;
        _formsAuthenticationProvider = formsAuthenticationProvider;
    }

    public void PresenceChange(string presence)
    {
        var user = _userRepository.FindById(_formsAuthenticationProvider.GetUserId());
        var rosterEntry = Mapper.Map<User, RosterEntryDto>(user);
        rosterEntry.Presence = presence;
        Clients.updatePresence(rosterEntry);
    }
}

这是我的 Ninject 引导程序:

Namespace SLx.Web.App_Start
{
using System;
using System.Web;

using Microsoft.Web.Infrastructure.DynamicModuleHelper;

using Ninject;
using Ninject.Web.Common;

public static class NinjectWebCommon 
{
    private static readonly Bootstrapper bootstrapper = new Bootstrapper();

    public static void Start() 
    {
        DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
        DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
        bootstrapper.Initialize(CreateKernel);
    }

    public static void Stop()
    {
        bootstrapper.ShutDown();
    }

    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        // SignalR Ninject Resolver
        GlobalHost.DependencyResolver = new SignalR.Ninject.NinjectDependencyResolver(kernel);

        // WebApi Ninject Resolver
        GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);

        RegisterServices(kernel);
        return kernel;
    }


    private static void RegisterServices(IKernel kernel)
    {

    }        
}

我通过如下定义的 PresenceProxy 通知服务器端的客户端:

public class PresenceHubProxy : IPresenceHubProxy
{
    private readonly IHubContext _hubContext;

    public PresenceHubProxy()
    {
        _hubContext = GlobalHost.ConnectionManager.GetHubContext<PresenceHub>();
    }

    public void NotifyLogin(RosterEntryDto user)
    {
        _hubContext.Clients.updatePresence(user);
    }

    public void NotifyLogout(RosterEntryDto user)
    {
        _hubContext.Clients.updatePresence(user);
    }
}

代理工作正常,注入到控制器或其依赖项中,并且可以向客户端发送消息。

当客户端尝试通过 Javascript 调用 SignalR 时,我收到以下错误:

No parameterless constructor defined for this object.

看起来 Ninject 没有被调用,因为依赖项没有被注入到构造函数中。我需要做什么才能让依赖注入也适用于 Javascript 调用?

更新 -

根据 DFowler 的建议,我已经替换了 PostApplicationStart 中的解析器。调试我可以在即时窗口中看到 SignalR.GlobalHost.Resolver 的类型为 NinjectDependencyResolver 但它仍然无法正常工作我得到同样的错误 - 没有无参数的构造函数。

然后,我删除了 NinjectDependencyResolver NuGet 库并将源文件添加到我的解决方案中,并将其用于调试目的。对 GetService 和 GetServices 的调试表明在 NinjectDependencyResolver 中从未调用过这两种方法。

有任何想法吗?

4

2 回答 2

3

问题是我没有调用 RouteTable.Routes.MapHubs:

GlobalHost.DependencyResolver = new SignalRNinjectResolver(NinjectWebCommon.Kernel);
RouteTable.Routes.MapHubs(new SignalRNinjectResolver(NinjectWebCommon.Kernel));
于 2012-06-13T16:58:40.230 回答
2

从文档https://github.com/SignalR/SignalR/wiki/Extensibility

注意:不要覆盖 PreApplicationStart 中的全局解析器,它不会起作用,或者它只会在某些时候起作用。在 PostApplicationStart(使用 WebActivator)或 Global.asax 中进行。

于 2012-06-12T19:19:43.653 回答