简体   繁体   中英

Injecting controller into SignalR Hubs using Simple Injector

I want to inject a singleton controller into my hubs using Simple Injector.

I've already tried the following but I'm getting status 500 as a response now.

EventDataHub:

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:

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();
    }
}

Hub activator:

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);
    }
}

The Subscribe method seems to be unreachable from the client side. The hub constructor is executed.

Exception stack:

[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

Edit:

Moving the DI configuration from Startup.cs to global.asax throws this exception:

[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

I finally found the problem:

container.Verify() is breaking the registration of the IHubActivator . So it has to be called either afterwards, or never.

Additionally I removed the container registration for IHub , as it works without now. (I added it because container.Register<IEventDataController, EventDataController>(Lifestyle.Singleton) wasn't working at that time and that fixed it somehow)

So my final code in Startup.cs looks like this:

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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM