2016-06-19 4 views
2

Я пытаюсь заставить SignalR работать с Autofac. У меня есть репо раздели назад версию того, что я сделал здесь:Autofac injection IHubContext SignalR MVC

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

Это заимствовано из которых работает с использованием GlobalHost:

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

Это прекрасно работает с использованием HTE GlobalHost объект. Я попытался выполнить документацию на сайте Autofac о том, как внедрять службы SignalR, но я не могу заставить его работать. Это мой конфигурационный файл для регистрации своих зависимостей:

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

И я называю это из 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); 
    } 

} 

И у меня есть контроллер, который это впрыскивается в его contstructor:

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

     // using DI 
     _context = hubContext; 
    } 

Это, однако, дает мне сообщение о том, что контроллер не имеет конструктора по умолчанию (поэтому я предполагаю, что это проблема с тем, что мой IHubContext не найден).

Любая помощь будет отличной. Я сделал репо, что я говорю о том, что можно найти здесь для полного решения:

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

ответ

4

Я был в состоянии сделать это, но это не так чист, как я обычно нравится. Основная проблема здесь в том, что IHubContext не отражает то, что конкретно типа хаба это ... это всего лишь общий дескриптор. Так что я сделал это, чтобы создать именованную регистрацию в Autofac зарегистрировать IHubContext с помощью специального SignalR хаба:

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

Затем я создал специальные регистрации для объектов я буду инъекционными этим хабом в. Это может быть либо ApiController, либо, возможно, другая служба, которая затем вводится в контроллеры с использованием стандартной интеграции Autofac/WebApi. Эта «конкретная» регистрация - это часть, которую мне не нравится, но я не знаю, как это сделать. Вот что это будет выглядеть следующим образом:

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

Теперь Autofac должен признать, что вы хотите, чтобы ввести IHubContext в TaskController и предоставить конкретную регистрацию имени EventHub при введении его.

+0

Спасибо Сэм. Нужно ли добавлять атрибут named к самому узлу? Или он использует имя класса? – sethreidnz

+0

Он должен использовать класс, который вы использовали при вызове GetHubContext <>() при регистрации. Мне не нужно ничего добавлять к самому центру. –