Подтвердить что ты не робот

SignalR + Autofac + OWIN: Почему не работает GlobalHost.ConnectionManager.GetHubContext?

Я пытаюсь использовать OWIN, SignalR и Autofac в одном проекте.

Я настраиваю вещи в отношении signalR следующим образом:

       // Create the AutoFac container builder:
        var builder = new ContainerBuilder();

        // ...[Register various other things in here]...

        // register signalR Hubs
        builder.RegisterHubs(Assembly.GetExecutingAssembly());

        // Build the container:
        var container = builder.Build();

        // Configure SignalR with the dependency resolver.
        app.MapSignalR(new HubConfiguration
        {
            Resolver =  new AutofacDependencyResolver(container)
        });

Моя проблема в том, что, когда я использую интеграцию Autofac SignalR, я больше не могу получить контекст Контакта signalR на сервере (например, в контроллере webapi) и поэтому не может отправлять сообщения с серверной стороны подключенным клиентам. Что-то вроде следующего: как я это делаю, когда не использую интеграцию сигналов Autofac signalR:

var hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
hubContext.Clients.All.notification("Test Message");

Но это не сработает, когда я добавляю Autofac в микс - я не получаю сообщение об ошибке, и я действительно получаю hubContext, но называет его фактически не добирается до клиентов.

Если я прокомментирую использование распознавателя зависимостей для signalR в вызове MapSignalR, вызов GetHubContext снова работает, и сообщения успешно доходят до клиентов signalR, но, конечно, я больше не могу использовать IoC на своих концентраторах. например.

        // Configure SignalR with the dependency resolver.
        app.MapSignalR(new HubConfiguration
        {
            // Resolver =  new AutofacDependencyResolver(container)
        });

Может ли кто-нибудь сказать мне, почему использование AutofacDependencyResolver останавливает работу GlobalHost.ConnectionManager.GetHubContext правильно?

ПРИМЕЧАНИЕ. Еще одна вещь, которую я попробовал, вместо использования GlobalHost.ConnectionManager.GetHubContext() Я попытался ввести IConnectionManager в контроллер webapi, из которого я хочу отправить сообщение клиентам, а затем вызвать GetHubContext, но Autofac не удалось разрешить IConnectionManager.

Я нашел следующую статью Piotr Szmyd, которая, по-видимому, позволяет это:

http://www.szmyd.com.pl/blog/wiring-signalr-with-autofac

но это, по-видимому, основано на устаревших строках signalR, и, хотя, похоже, для него существует пакет nuget:

http://www.nuget.org/packages/SignalR.AutoFac/

он также кажется устаревшим.

4b9b3361

Ответ 1

Если вы используете настраиваемый зависимый преобразователь с SignalR, вы больше не можете использовать GlobalHost, если вы его не измените:

GlobalHost.DependencyResolver = new AutofacDependencyResolver(container);
IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();

// A custom HubConfiguration is now unnecessary, since MapSignalR will
// use the resolver from GlobalHost by default.
app.MapSignalR();

Если вы не хотите изменять GlobalHost, вам придется вручную разрешить ваш IConnectionManager:

IDependencyResolver resolver = new AutofacDependencyResolver(container);
IHubContext hubContext = resolver.Resolve<IConnectionManager>().GetHubContext<MyHub>();

app.MapSignalR(new HubConfiguration
{
    Resolver = resolver
});

Ответ 2

Для получения полного ответа, с SignalR, Autofac и OWIN, я сделал следующее:

// register IPersistantConnectionContext for access to SignalR connection
// and IDependencyResolver to enable inection of the container into its
// construction for the config object.
var builder = new ContainerBuilder();
builder.RegisterType<Autofac.Integration.SignalR.AutofacDependencyResolver>()
    .As<IDependencyResolver>()
    .SingleInstance();
builder.Register((context, p) =>
        context.Resolve<IDependencyResolver>()
            .Resolve<Microsoft.AspNet.SignalR.Infrastructure.IConnectionManager>()
            .GetConnectionContext<SignalRConnection>());

// ... other registrations

var container = builder.Build();

var signalrConfiguration = new ConnectionConfiguration
{
    Resolver = container.Resolve<IDependencyResolver>(),
};

app.UseAutofacMiddleware(container);

app.MapSignalR<SignalRConnection>("/signalr", signalrConfiguration);

// ... other middleware

В моих контроллерах я включил параметр типа IPersistentConnectionContext и ввел правильный экземпляр.

Я использовал PersistentConnection, но он должен быть похож на Hubs.

Ответ 3

Чтобы расширить ответ Nathan, я использую что-то похожее с ключевой строкой

builder.RegisterHubs(Assembly.GetExecutingAssembly()).SingleInstance();

в Startup.cs.

Строка "SingleInstance()" гарантирует, что во всем приложении используется только один "экземпляр" концентратора.

Затем я просто использую простое вложение зависимостей в конструктор контроллера, чтобы получить указатель на концентратор.