Search code examples
c#dependency-injectionasp.net-coreautofacasp.net-core-signalr

SignalR Dependency Injection for ASP.NET Core v2.0 using Autofac


Is it possible to use dependency injection to inject dependencies into SignalR on ASP.NET Core v2.0?

Assuming the following hub and dependency:

public MyHub : Hub {

    private readonly IMyDependency dependency;

    public MyHub(IMyDependency dependency) {
        this.dependency = dependency;
    }
}

public void MyDependency : IDependency
{
    public void MyMethod() {
        Console.WriteLine("I'm a dependency!");
    }
}

I've scoured a bit of the web and there isn't anything obvious out there. I found this tutorial which at first seemed quite promising until I realised it was for Microsoft.AspNetCore.SignalR.Server which didn't ship in the end.

At the moment I have the following setup using Autofac and it's not working:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
        services.AddSignalR();

        // Configue Autofac
        var containerBuilder = new ContainerBuilder();

        containerBuilder.RegisterModule<MyModule>();

        // Configure SignalR hubs for dependency injection
containerBuilder.RegisterSignalRHubs(typeof(Startup).GetTypeInfo().Assembly);

        containerBuilder.Populate(services);
        var container = containerBuilder.Build();
        return new AutofacServiceProvider(container);
    }
}

public static class AutoFacExtensions
{
    public static IRegistrationBuilder<object, ScanningActivatorData, DynamicRegistrationStyle> RegisterSignalRHubs(this ContainerBuilder builder, params Assembly[] assemblies)
    {
        return builder.RegisterAssemblyTypes(assemblies)
            .Where(t => typeof(IHub).IsAssignableFrom(t))
            .ExternallyOwned();
    }
}

public class MyModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<MyDependency>().As<IMyDependency>();
    }
}

It looks like the IHub interface doesn't exist anymore. I tried IHubContext<MyHub> in the hope that this might work with the latest version but sadly not.

When I have dependencies in my hub's constructor, the hub isn't created despite all of the dependencies registered with Autofac.

How can I achieve this with the lastest version 1.0.0.0-alpha2-final?


Solution

  • The example given in the question does work with version 1.0.0.0-alpha2-final of Microsoft.AspNetCore.SignalR with one slight tweak, use Hub rather than the now non-existent IHub.

    public static class AutoFacExtensions
    {
        public static IRegistrationBuilder<object, ScanningActivatorData, DynamicRegistrationStyle> RegisterSignalRHubs(this ContainerBuilder builder, params Assembly[] assemblies)
        {
            // typeof(Hub), not typeof(IHub)
            return builder.RegisterAssemblyTypes(assemblies)
                .Where(t => typeof(Hub).IsAssignableFrom(t))
                .ExternallyOwned();
        }
    }
    

    Ensure that all of your dependencies are satisfied by assigning them to a controller. I'm not sure at this point how to troubleshoot broken dependencies when injecting into a SignalR hub with this method.