Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I set up SignalR Hub Dependency Injection in ASP.NET 5 (vNext)?

Trying to do dependency injection into my SignalR Hub class using the SignalR-Server which is part of ASP.NET 5 (repo). I tried to figure this out from the tutorial at this link but I can't seem to identify how I can do this given that GlobalHost is no longer available. Here's what I'm trying to do:

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddSignalR();
    services.AddSingleton<IState, State>();
}

public void Configure(IApplicationBuilder app)
{
    app.UseSignalR();
}

MyHub.cs

public class MyHub : Hub
{
    public IState State { get; set; }

    // SignalR accepts this parameterless ctor
    public MyHub()
    {
    }

    // SignalR won't use this because it has a parameter
    public MyHub(IState state)
    {
        State = state;
    }
}

How can I get SignalR-Server to use the MyHub(IState state) constructor injecting the required dependencies?

like image 629
Martin Tracey Avatar asked Aug 21 '15 22:08

Martin Tracey


2 Answers

I managed to resolve this by adding my State class as a Singleton for IState in Startup.ConfigureServices, and then making a ServiceProvider property publicly available on my Startup.cs class. From there, I was able to GetRequiredService within the constructor of my SignalR Hub class. It isn't the ideal solution and hopefully I'll be able to adjust this to use constructor/property injection as the platform reaches RC.

Here's my code:

Startup.cs

public static IServiceProvider __serviceProvider;

public void ConfigureServices(IServiceCollection services)
{
    services.AddSignalR();
    services.AddSingleton<IState, State>();
    __serviceProvider = services.BuildServiceProvider();
}

public void Configure(IApplicationBuilder app)
{
    app.UseSignalR();
}

MyHub.cs

public class MyHub : Hub
{
    public IState State { get; set; }

    public MyHub()
    {
        State = (IState) Startup.__serviceProvider.GetRequiredService(typeof (IState));
    }

    public override Task OnConnected()
    {
        State.Clients = Clients;
        State.Groups = Groups;
        return base.OnConnected();
    }
}

In this way, I was able to set properties and call methods on IState implementing objects from within MyHub, allowing me to persist my app state in memory.

like image 140
Martin Tracey Avatar answered Sep 29 '22 07:09

Martin Tracey


the best way (for Asp.Net 5) create a custom resolver to DefaultDependencyResolver that receives IServiceProvider:

 public class CustomSignalRDependencyResolver : DefaultDependencyResolver
{
    private readonly IServiceProvider _serviceProvider;

    public CustomSignalRDependencyResolver(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public override object GetService(Type serviceType)
    {
        var service = _serviceProvider.GetService(serviceType);

        return service ?? base.GetService(serviceType);
    }


}

Then on StartUp class

 public void ConfigureServices(IServiceCollection services)
    {

         services.AddSingleton<IState, State>();

        //... other services


        GlobalHost.DependencyResolver = new CustomSignalRDependencyResolver(services.BuildServiceProvider());

    }
like image 21
Allan Clempe Avatar answered Sep 29 '22 09:09

Allan Clempe