c# Asp.Net проблема связки событий и Hub(хабов) из SignalR

Делаю мессенджер. Хочу создать event, который будет реагировать на изменение списка пользователей(обычный массив) и отправлять всем подключенным пользователям этот список.

Но проблема в том, что Hub имеет специфичный жизненный цикл, и у меня не получается где-то грамотно и единожды инициализировать метод, который будет вызываться при событии. Как понимаю, каждый экземпляр Hub'a содержит свой контекст для каждого пользователя, и "умирает" после выполнения запроса. ChatManager у меня статичен и один для всех хабов. Само событие лежит в ChatManager

ChatHub

internal class ChatHub : Hub
    {
        private readonly static ChatManager ChatManager = new ChatManager(); // тут всякая логика

        public async Task SendMembersInfo() // метод, который хочу вызывать при событии
        {
            MembersInfo membersInfo = ChatManager.CreateMembersInfo();
            string jsonMembersInfo = JsonHelper.Serialize(membersInfo);
            await this.Clients.All.SendAsync("ReceiveMembersInfo", jsonMembersInfo);
        }

        public override Task OnConnectedAsync()
        {
            ChatManager.ConnectUser(Context.ConnectionId);
            return base.OnConnectedAsync();
        }
        public override Task OnDisconnectedAsync(Exception? exception)
        {
            ChatManager.DisconnectUser(Context.ConnectionId);
            return base.OnDisconnectedAsync(exception);
        }
    }

ChatManager

namespace ServerSide.Models
{
    internal class ChatManager
    {
        public List<User> Users { get; } = new List<User>();

        public delegate Task Update(); 
        public event Update OnUsersUpdate; // EVENT

        public MembersInfo CreateMembersInfo()
        {
            return new MembersInfo(Users);
        }

        public bool ConnectUser(string connectionId)
        {
            if (string.IsNullOrEmpty(connectionId)) return false;
            if (Users.FirstOrDefault(user => user.ConnectionId == connectionId) != null) return false;

            Users.Add(new User(connectionId));
            OnUsersUpdate(); // вызываю событие
            return true;
        }
        public void DisconnectUser(string connectionId)
        {
            User? user = Users.FirstOrDefault(user => user.ConnectionId == connectionId);
            if (user == null) return;

            Users.Remove(user);
            OnUsersUpdate(); // вызываю событие
        }

    }
}

Где подключить событие в ChatHub?

Все прекрасно работает, если в конструкторе Хаба инициализировать работу с событием, но ведь это получается, что он привязывается много раз. Можно ли как-то грамотно его привязать?

public ChatHub()
{
    ChatManager.OnUsersUpdate += this.SendMembersInfo;
}

Буду благодарен за предложения.


Ответы (1 шт):

Автор решения: PashaPash

Уберите статику

private readonly static ChatManager ChatManager = new ChatManager()`

Вставьте зависимость на ChatManager через конструктор

private readonly ChatManager _сhatManager;

public ChatHub(ChatManager сhatManager)
{
    _chatManager = сhatManager;
}

Зарегистрируйте ChatManager в IoC:

builder.Services.AddSingleton<ChatManager>();

И прокидывайте Hub во все вызовы ChatManager, где нужно отправить сообщение всем (ну или отправляйте прямо из Hub)

→ Ссылка