我最近升级到优秀的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 Bootstrapper:
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,因为依赖项没有被注入到构造函数中。我还需要做些什么才能让Dependency Injection也适用于Javascript调用?
更新 -
根据DFowler的建议,我已经在PostApplicationStart中替换了Resolver。调试我可以在立即窗口中看到SignalR.GlobalHost.Resolver的类型为NinjectDependencyResolver但它仍然无法正常工作我得到了同样的错误 - 没有无表情的构造函数。
然后我删除了NinjectDependencyResolver NuGet Library并将源文件添加到我的解决方案中,并将其用于调试目的。在GetService和GetServices上进行调试表明,在NinjectDependencyResolver中都没有调用任何方法。
任何想法?
答案 0 :(得分:3)
问题是我没有调用RouteTable.Routes.MapHubs:
GlobalHost.DependencyResolver = new SignalRNinjectResolver(NinjectWebCommon.Kernel);
RouteTable.Routes.MapHubs(new SignalRNinjectResolver(NinjectWebCommon.Kernel));
答案 1 :(得分:2)
来自文档https://github.com/SignalR/SignalR/wiki/Extensibility:
注意:请勿在PreApplicationStart中覆盖全局解析程序,它不起作用,或者它只在某些时候起作用。在PostApplicationStart(使用WebActivator)或Global.asax。
中执行