Отправлять сообщения через SignalR HubContext из метода в проекте за пределами того места, где расположены концентраторы

Dec 08 2020

У меня есть проект WebAPI, в котором уровни API, сервиса и данных находятся в отдельных проектах одного и того же решения. В рамках метода в моем проекте службы я хочу отправить сообщение подключенным клиентам концентратора в проекте API. Пока что все найденные мной примеры содержат все в одном проекте и используют контроллер в качестве примера отправки сообщения через концентратор.

Я пробовал внедрение зависимостей (Autofac), однако мне не удалось получить ссылку на MessageHub.

[HubName("messages")]
public class MessageHub : Hub
{
    public void ShowNewMessage(string message)
    {
        Clients.All.showMessageOnPage(message);
    }
}

Мою попытку внедрения можно увидеть здесь: Внедрить SignalR IHubContext в уровень обслуживания с помощью Autofac

Ответы

1 AlexanderI. Dec 08 2020 at 04:41

Просмотрите этот вариант:

  1. Определите общий интерфейс концентратора в своем проекте уровня службы (или, лучше, домена). Что-то вроде IMessageBroker.
  2. Внутри вашего проекта уровня презентации (WebAPI) реализуйте этот интерфейс и используйте его IConnectionManagerдля получения HubContext.
  3. Зарегистрируйте интерфейс в контейнере IoC (Autofac) на уровне представления.
  4. Внедрить интерфейс внутри службы приложений

Псевдокод:

Уровень домена:

public interface IMessageBroker
{
    void ShowNewMessage(string message)
}

Уровень обслуживания:

public class NotificationService: INotificationService
{
    private readonly IMessageBroker _messageBroker;

    public NotificationService(IMessageBroker messageBroker)
    {
        _messageBroker = messageBroker;
    }

    public void RunNotification(string message)
    {
        _messageBroker.ShowNewMessage(message);
    }
}

Уровень презентации:

[HubName("messages")]
public class MessageHub: Hub
{
    public void ShowNewMessage(string message)
    {
        Clients.All.showMessageOnPage(message);
    }
}


public class MessageBroker: IMessageBroker
{
    private readonly IConnectionManager _connectionManager;

    public MessageBroker(IConnectionManager connectionManager)
    {
        _connectionManager = connectionManager;
    }

    public void ShowNewMessage(string message)
    {
        var hub = _connectionManager.GetHubContext<MessageHub>();
        // Use Hub Context and send message
    }
}

Регистрация Autofac (уровень представления):

// Register Hubs
builder.RegisterHubs(Assembly.GetExecutingAssembly());

// Register Autofac resolver into container to be set into HubConfiguration later
builder.RegisterType<AutofacDependencyResolver>().As<IDependencyResolver>().SingleInstance();

// Register ConnectionManager as IConnectionManager so that you can get hub context via IConnectionManager injected to your service
builder.RegisterType<ConnectionManager>().As<IConnectionManager>().SingleInstance();

// Register interface
builder.RegisterType<MessageBroker>().As<IMessageBroker>();

Также аналогичная тема SO доступна здесь .