我在我的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));
}
}
}
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);
}
}
由于
答案 0 :(得分:8)
将Structuremap放入SignalR实际上非常简单。首先,您要创建自己的解析器:
Usings:
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等)。
接下来,您需要在容器中注册它(我喜欢使用注册表):
Usings:
using SignalR.Infrastructure;
using StructureMap.Configuration.DSL;
类别:
public class ExtensionsRegistry : Registry
{
public ExtensionsRegistry()
{
For<IDependencyResolver>().Add<StructureMapResolver>();
}
}
最后,您需要告诉SignalR使用您的解析器而不是默认值:
Global :: Application_Start或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>());
现在,您可以将容器知道的任何依赖项注入集线器本身:
[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)); });
}
}
答案 1 :(得分:5)
您是否按照此处的说明操作: - https://github.com/SignalR/SignalR/wiki/Extensibility?
您需要使用AspNetHost.SetResolver
。
答案 2 :(得分:2)
我知道这是一个旧线程,但对于那些想知道在较新版本的signalR中AspNetHost.SetResolver在哪里的人,你可以在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);
}
答案 3 :(得分:1)
将类似内容添加到App_Start文件夹中的文件中。此代码段适用于Ninject,因此只需替换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>();
}
}
}