【问题标题】:Send messages via SignalR HubContext from method in project outside where Hubs are located通过 SignalR HubContext 从集线器所在的项目中的方法发送消息
【发布时间】:2020-12-07 18:49:38
【问题描述】:

我有一个 WebAPI 项目,其中 API、服务和数据层都位于同一解决方案的不同项目中。作为我的服务项目中方法的一部分,我想向 API 项目中集线器的连接客户端发送消息。到目前为止,我发现的所有示例都在一个项目中包含所有内容,并使用控制器作为通过集线器发送消息的示例。

我已经尝试过依赖注入 (Autofac),但是我无法获得对 MessageHub 的引用。

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

可以在这里看到我的 Injecting 尝试:Inject SignalR IHubContext into service layer with Autofac

【问题讨论】:

  • 好吧,你不能引用 MessageHub 类,因为你的 Service 项目可能没有引用 WebAPI 项目。
  • @Dawid 我明白这一点。我无法添加引用,因为这会创建循环引用。我需要能够从我的服务层内部发送集线器消息。
  • 您可以将 Hub 放在两个项目都引用的“共享项目”中。
  • @Brennan 我以前从未见过这样做过。那个共享项目会是一个网络项目吗? javascript 客户端仍然必须能够访问中心。

标签: c# asp.net-web-api signalr autofac hangfire


【解决方案1】:

请查看此选项:

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

here 也有类似的 SO 主题。

【讨论】:

  • INotificationService 有什么特别之处吗?我只是根据 NotificationService 生成的。
  • INotificationService 没有什么特别之处。这只是一个例子。还可以在 post 上查看非常相似的实现。
  • 无法解析构造函数 'Void .ctor(ShopAP.API.Data.Repositories.Interfaces.IShopAPRepository, AutoMapper.IMapper, ShopAP.API. Domain.Hubs.IMessageBroker)
  • 你在Autofac中注册接口了吗?
  • builder.RegisterHubs(Assembly.GetExecutingAssembly());
猜你喜欢
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-16
  • 2017-04-24
  • 1970-01-01
  • 1970-01-01
  • 2011-11-24
相关资源
最近更新 更多