我在我的MVC3应用程序中使用SignalR,并且由于我已经在我的控制器上实现了StructureMap依赖注入,所以我想在我的中心做同样的事情,但是我似乎无法使其工作。
请告诉我我的代码如下:
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)); } } }
通知书
[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); } }
谢谢
解决方法
将Structuremap转换成SignalR其实很简单。首先要创建自己的解析器:
StructureMap Resolver
用途:
using SignalR.Infrastructure; using StructureMap;
类:
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)); } }
这里的想法是尝试使用容器来解决依赖关系,如果没有依赖关系,将其传递给默认解析器。这样,您就不用担心SignalR中的所有其他依赖项,只能将注意力集中到(Hubs,ConnectionIdFactory,MessageBus等)上。
解决方案和集线器的绑定
用途:
using SignalR.Infrastructure; using StructureMap.Configuration.DSL;
类:
public class ExtensionsRegistry : Registry { public ExtensionsRegistry() { For<IDependencyResolver>().Add<StructureMapResolver>(); } }
拆卸变更
最后,您将要告诉SignalR使用您的解析器而不是默认值:
Global :: Application_Start或WebActivator :: Pre_Start
用途:
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与注入的依赖关系
现在,您可以将容器知道的任何依赖项注入到集线器本身中:
[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)); }); } }