Autofac injection of IHubContext SignalR MVC

一曲冷凌霜 提交于 2020-12-26 08:09:33

问题


I am trying to get SignalR working with Autofac. I have a repo of a stripped back version of what I have done here:

https://github.com/justsayno/signalr-autofac

This is adapted from which works using GlobalHost:

https://github.com/sstorie/experiments/tree/master/angular2-signalr

That works just fine using hte GlobalHost object. I have attempted to follow the documentation on Autofac's site about how to inject SignalR services but I cannot get it to work. This is my config file for registering my dependencies:

public static IContainer RegisterDependencies()
    {
        // Create your builder.
        var builder = new ContainerBuilder();

        //register controllers in DI
        builder.RegisterControllers(Assembly.GetExecutingAssembly());
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());

        // Register SignalR hubs
        builder.RegisterHubs(Assembly.GetExecutingAssembly());

        return builder.Build();
    }

And I call this from startup.cs:

public class Startup
{
    public static IContainer Container { get; set; }
    public void Configuration(IAppBuilder app)
    {
        var config = GlobalConfiguration.Configuration;

        // configure IoC container
        Container = AutofacConfiguration.RegisterDependencies();

        //set dependency resolver from WebAPI and MVC
        config.DependencyResolver = new AutofacWebApiDependencyResolver(Container);
        DependencyResolver.SetResolver(new Autofac.Integration.Mvc.AutofacDependencyResolver(Container));

        //register Autofac Middleware
        app.UseAutofacMiddleware(Container);

        app.Map("/signalr", a =>
        {
            a.UseCors(CorsOptions.AllowAll);
            var hubConfiguration = new HubConfiguration
            {
                Resolver = new Autofac.Integration.SignalR.AutofacDependencyResolver(Container)
            };
            a.RunSignalR(hubConfiguration);
        });

        // This server will be accessed by clients from other domains, so
        //  we open up CORS
        //
        app.UseCors(CorsOptions.AllowAll);

        // Build up the WebAPI middleware
        //
        var httpConfig = new HttpConfiguration();
        httpConfig.MapHttpAttributeRoutes();
        app.UseWebApi(httpConfig);
    }

}

And I have a controller that has this injected into its contstructor:

 public TaskController(IHubContext hubContext)
    {
        // Commented out hard coded global host version
        //
        //_context = GlobalHost.ConnectionManager.GetHubContext<EventHub>();

        // using DI
        _context = hubContext;
    }

This however gives me an error about the controller not having a default constructor (so I assume this is a problem with my IHubContext not being found).

Any help would be great. I have made a repo of what I am talking about that can be found here for a complete solution:

https://github.com/justsayno/signalr-autofac


回答1:


I've been able to do this, but it's not as clean as I would normally like. The primary issue here is that IHubContext does not reflect what specific type of hub it is...it's just a generic handle. So what I've done is to create a named registration within Autofac to register IHubContext using a specific SignalR hub:

builder.Register(ctx => 
    ctx.Resolve<IDependencyResolver>()
       .Resolve<IConnectionManager>()
       .GetHubContext<EventHub>())
       .Named<IHubContext>("EventHub");

Then I set up specific registrations for the objects I'll be injecting this hub into. This could be either an ApiController, or perhaps some other service that is then injected into controllers using the standard Autofac/WebApi integration. This "specific" registration is the piece I don't like, but I don't know of a cleaner way around it. Here's what that would look like:

builder.RegisterType<TaskController>()
       .WithParameter(
           new ResolvedParameter(
               (pi, ctx) => pi.ParameterType == typeof(IHubContext),
               (pi, ctx) => ctx.ResolveNamed<IHubContext>("EventHub")
       )
 );

Now Autofac should recognize that you want to inject IHubContext into the TaskController and provide the specific registration named EventHub when injecting it.



来源:https://stackoverflow.com/questions/37912330/autofac-injection-of-ihubcontext-signalr-mvc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!