Создание экземпляра IHubContext в ASP.NET Core

Я использую SignalR в разных частях своего веб-проекта. В моих контроллерах и HostedService, похоже, все работает нормально. Клиенты создают экземпляры соединений с моим концентратором, и я могу связываться с ними обратно, используя экземпляр IHubContext, введенный в конструктор каждого контроллера / размещенной службы.

У меня есть еще один синглтон, работающий в фоновом режиме (без HosteService или BackgroundTask). Этот класс также вводит IHubContext в конструктор. Тем не менее каждый раз, когда он вызывается, кажется, что у этого синглтона есть другой экземпляр IHubContext, поскольку в этом контексте нет клиентов / групп, подключенных к нему.

Этот класс регистрируется как это в функции запуска:

services.AddSingleton<IServiceEventHandler<TourMonitorEvent>, TourMonitorEventHandler>();

Чтобы настроить SignalR, я делаю следующее в ConfigureServices:

services.AddSignalR().AddNewtonsoftJsonProtocol();

и следующее в configure:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<MyHubClass>("/hubEndpoint");
    endpoints.MapControllers();
});

IHubContext не внедряется как в Controllers / Hostedservices, так и в синглтон следующим образом:

public class MySingleton : IHandler<SomeGenericClass>
{
    private readonly IHubContext<MyHubClass> _hubContext;

    public MySingleton(IHubContext<MyHubClass> hubContext)
    {
        _hubContext = hubContext;
    } 
}

Создается ли экземпляр Controllers / HosteService иначе, чем мой синглтон, и это может повлиять на создание экземпляра IHubContext?


person mh133    schedule 20.03.2020    source источник
comment
Пожалуйста, предоставьте код, как вы вводите IHubContext;)   -  person Kiril1512    schedule 20.03.2020
comment
@ Kiril1512 Я отредактировал, чтобы ответить, добавив инъекцию IHubContext   -  person mh133    schedule 20.03.2020


Ответы (1)


Как сказано в документация:

Хабы временные.

Итак, поскольку ваш Singleton не является HostedService или BackgroundTask, я бы рекомендовал внедрить концентратор с помощью DI.

private IHubContext<MyHubClass, IMyHubClass> MyHubClass
{
    get
    {
        return this.serviceProvider.GetRequiredService<IHubContext<MyHubClass, IMyHubClass>>();
    }
}

Попробуйте это и убедитесь, что контекст соответствует вашим ожиданиям.

person Kiril1512    schedule 20.03.2020
comment
Понятно. Итак, если концентраторы временные, как получается, что я получаю один и тот же концентратор (я предполагаю, что, поскольку оба имеют одинаковое состояние) на двух разных контроллерах в двух разных вызовах? - person mh133; 20.03.2020
comment
У вас есть контекст, а не концентратор. - person Kiril1512; 20.03.2020
comment
Точно, а контекст одноэлементный, не так ли? Разве это не означает, что у меня один и тот же объект (контекст), созданный один раз и, следовательно, один и тот же концентратор (временный)? По крайней мере, это поведение, которое я наблюдаю в Controllers / Hostedservices. У меня такой же синглтон с тем же хабом (состоянием). - person mh133; 20.03.2020
comment
ASP.NET Core имеет структуру внедрения зависимостей, которая устраняет необходимость в этом глобальном синглтоне. Когда методы концентратора вызываются из-за пределов класса концентратора, вызывающий объект не связан с вызовом. Следовательно, нет доступа к свойствам ConnectionId, Caller и Others. - person Kiril1512; 20.03.2020