使用简单注入器将控制器注入 SignalR 集线器
Injecting controller into SignalR Hubs using Simple Injector
我想使用 Simple Injector 将单例控制器注入我的集线器。
我已经尝试了以下方法,但我现在收到状态 500 作为响应。
集线器代码:
public class EventDataHub : Hub
{
private static IEventDataController _dataController;
public EventDataHub(IEventDataController dataController)
{
_dataController = dataController;
}
public void Subscribe(string signal)
{
_dataController.Subscribe(signal, Context.ConnectionId);
}
}
Startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
var container = new Container();
var hybridLifestyle = Lifestyle.CreateHybrid(
lifestyleSelector: () => HttpContext.Current != null,
trueLifestyle: new WebRequestLifestyle(),
falseLifestyle: new LifetimeScopeLifestyle());
container.Register<IEventDataController, EventDataController>(Lifestyle.Singleton);
container.Register<IHub, EventDataHub>(hybridLifestyle);
container.Verify();
var activator = new SimpleInjectorHubActivator(container);
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => activator);
app.MapSignalR();
}
}
集线器激活器
public class SimpleInjectorHubActivator : IHubActivator
{
private readonly Container _container;
public SimpleInjectorHubActivator(Container container)
{
_container = container;
}
public IHub Create(HubDescriptor descriptor)
{
return (IHub)_container.GetInstance(descriptor.HubType);
}
}
Subscribe
方法似乎无法从客户端访问。执行集线器构造函数。
异常堆栈:
[MissingMethodException: no parameterless constructor defined for this object]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean
publicOnly, Boolean noCheck, Boolean& canBeCached,
RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean
skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +113
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly,
Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
+206 System.Activator.CreateInstance(Type type, Boolean nonPublic) +83 System.Activator.CreateInstance(Type type) +11 Microsoft.AspNet.SignalR.Hubs.DefaultHubActivator.Create(HubDescriptor
descriptor) +84
Microsoft.AspNet.SignalR.Hubs.DefaultHubManager.ResolveHub(String
hubName) +27
Microsoft.AspNet.SignalR.Hubs.HubDispatcher.CreateHub(IRequest
request, HubDescriptor descriptor, String connectionId,
StateChangeTracker tracker, Boolean throwIfFailedToCreate) +386
Microsoft.AspNet.SignalR.Hubs.HubDispatcher.OnReceived(IRequest
request, String connectionId, String data) +400
Microsoft.AspNet.SignalR.<>c__DisplayClass64_1.b__5()
+34 Microsoft.AspNet.SignalR.TaskAsyncHelper.FromMethod(Func`1 func) +28
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) +58
Microsoft.AspNet.SignalR.Transports.d__40.MoveNext()
+742 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) +58 Microsoft.Owin.Mapping.d__0.MoveNext() +385
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) +58
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.d__5.MoveNext()
+187 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) +58
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.d__2.MoveNext()
+185 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult
ar) +69
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult
ar) +64
System.Web.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
+380 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
编辑:
将 DI 配置从 Startup.cs 移动到 global.asax 会引发此异常:
[ArgumentNullException: value cannot be null. Parametername:
s] System.IO.StringReader..ctor(String s) +11377176
Microsoft.AspNet.SignalR.Json.JsonSerializerExtensions.Parse(JsonSerializer
serializer, String json) +63
Microsoft.AspNet.SignalR.Hubs.HubRequestParser.Parse(String data,
JsonSerializer serializer) +21
Microsoft.AspNet.SignalR.Hubs.HubDispatcher.OnReceived(IRequest
request, String connectionId, String data) +40
Microsoft.AspNet.SignalR.<>c__DisplayClass64_1.b__5()
+34 Microsoft.AspNet.SignalR.TaskAsyncHelper.FromMethod(Func`1 func) +28
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) +58
Microsoft.AspNet.SignalR.Transports.d__40.MoveNext()
+742 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) +58 Microsoft.Owin.Mapping.d__0.MoveNext() +385
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) +58
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.d__5.MoveNext()
+187 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task
task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) +58
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.d__2.MoveNext()
+185 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult
ar) +69
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult
ar) +65
System.Web.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
+380 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
我终于找到问题了:
container.Verify()
正在破坏 IHubActivator
的注册。所以它要么在之后被调用,要么永远不会被调用。
此外,我删除了 IHub
的容器注册,因为它现在可以正常工作。 (我添加它是因为 container.Register<IEventDataController, EventDataController>(Lifestyle.Singleton)
当时没有工作并且以某种方式修复了它)
所以我在 Startup.cs 中的最终代码如下所示:
public void Configuration(IAppBuilder app)
{
var container = new Container();
container.Register<IEventDataController, EventDataController>(Lifestyle.Singleton);
var activator = new SimpleInjectorHubActivator(container);
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => activator);
app.MapSignalR();
}
我想使用 Simple Injector 将单例控制器注入我的集线器。
我已经尝试了以下方法,但我现在收到状态 500 作为响应。
集线器代码:
public class EventDataHub : Hub
{
private static IEventDataController _dataController;
public EventDataHub(IEventDataController dataController)
{
_dataController = dataController;
}
public void Subscribe(string signal)
{
_dataController.Subscribe(signal, Context.ConnectionId);
}
}
Startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
var container = new Container();
var hybridLifestyle = Lifestyle.CreateHybrid(
lifestyleSelector: () => HttpContext.Current != null,
trueLifestyle: new WebRequestLifestyle(),
falseLifestyle: new LifetimeScopeLifestyle());
container.Register<IEventDataController, EventDataController>(Lifestyle.Singleton);
container.Register<IHub, EventDataHub>(hybridLifestyle);
container.Verify();
var activator = new SimpleInjectorHubActivator(container);
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => activator);
app.MapSignalR();
}
}
集线器激活器
public class SimpleInjectorHubActivator : IHubActivator
{
private readonly Container _container;
public SimpleInjectorHubActivator(Container container)
{
_container = container;
}
public IHub Create(HubDescriptor descriptor)
{
return (IHub)_container.GetInstance(descriptor.HubType);
}
}
Subscribe
方法似乎无法从客户端访问。执行集线器构造函数。
异常堆栈:
[MissingMethodException: no parameterless constructor defined for this object]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +113
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +206 System.Activator.CreateInstance(Type type, Boolean nonPublic) +83 System.Activator.CreateInstance(Type type) +11 Microsoft.AspNet.SignalR.Hubs.DefaultHubActivator.Create(HubDescriptor descriptor) +84
Microsoft.AspNet.SignalR.Hubs.DefaultHubManager.ResolveHub(String hubName) +27
Microsoft.AspNet.SignalR.Hubs.HubDispatcher.CreateHub(IRequest request, HubDescriptor descriptor, String connectionId, StateChangeTracker tracker, Boolean throwIfFailedToCreate) +386
Microsoft.AspNet.SignalR.Hubs.HubDispatcher.OnReceived(IRequest request, String connectionId, String data) +400
Microsoft.AspNet.SignalR.<>c__DisplayClass64_1.b__5() +34 Microsoft.AspNet.SignalR.TaskAsyncHelper.FromMethod(Func`1 func) +28
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.AspNet.SignalR.Transports.d__40.MoveNext() +742 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58 Microsoft.Owin.Mapping.d__0.MoveNext() +385
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.d__5.MoveNext() +187 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.d__2.MoveNext() +185 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar) +69
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult ar) +64
System.Web.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +380 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
编辑:
将 DI 配置从 Startup.cs 移动到 global.asax 会引发此异常:
[ArgumentNullException: value cannot be null. Parametername: s] System.IO.StringReader..ctor(String s) +11377176
Microsoft.AspNet.SignalR.Json.JsonSerializerExtensions.Parse(JsonSerializer serializer, String json) +63
Microsoft.AspNet.SignalR.Hubs.HubRequestParser.Parse(String data, JsonSerializer serializer) +21
Microsoft.AspNet.SignalR.Hubs.HubDispatcher.OnReceived(IRequest request, String connectionId, String data) +40
Microsoft.AspNet.SignalR.<>c__DisplayClass64_1.b__5() +34 Microsoft.AspNet.SignalR.TaskAsyncHelper.FromMethod(Func`1 func) +28
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.AspNet.SignalR.Transports.d__40.MoveNext() +742 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58 Microsoft.Owin.Mapping.d__0.MoveNext() +385
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.d__5.MoveNext() +187 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +92
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +58
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.d__2.MoveNext() +185 Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.StageAsyncResult.End(IAsyncResult ar) +69
Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContext.EndFinalWork(IAsyncResult ar) +65
System.Web.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +380 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
我终于找到问题了:
container.Verify()
正在破坏 IHubActivator
的注册。所以它要么在之后被调用,要么永远不会被调用。
此外,我删除了 IHub
的容器注册,因为它现在可以正常工作。 (我添加它是因为 container.Register<IEventDataController, EventDataController>(Lifestyle.Singleton)
当时没有工作并且以某种方式修复了它)
所以我在 Startup.cs 中的最终代码如下所示:
public void Configuration(IAppBuilder app)
{
var container = new Container();
container.Register<IEventDataController, EventDataController>(Lifestyle.Singleton);
var activator = new SimpleInjectorHubActivator(container);
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => activator);
app.MapSignalR();
}