【问题标题】:Understanding SignalR- Hubs, Dependency Injection, and Controllers了解 SignalR-集线器、依赖注入和控制器
【发布时间】:2021-05-16 18:11:26
【问题描述】:

我一直在翻阅文档和论坛,试图了解 SignalR,但我陷入了困境。

我想要实现的是,在聊天应用程序中:将消息存储在 Hub 之外,以便每次用户加入聊天时,他们都可以看到在加入之前发送的所有消息。

所以看起来外部类是这样做的方法,所以我使用依赖注入来解决这个问题

In ChatHub.cs

namespace SignalRChat.Hubs
{
    public class ChatHub: Hub
    {

        public IChatStorage _chatStorage;

        public ChatHub(IChatStorage chatStorage)
        {
            _chatStorage = chatStorage;
        }
    // and so on

我在 ChatHub 中有一个方法可以向 chatStorage 发送消息,但我对如何将所有消息的列表从 chatStorage 发送回 ChatHub 甚至 JavaScript 感到困惑。似乎控制器是这样做的方法,但我不确定如何调用控制器的方法:

namespace SignalRChat.Controllers
{
    public class ChatController: Controller
    {
        private IHubContext<ChatHub> _hubContext;

        public ChatController(IHubContext<ChatHub> hubContext)
        {
            _hubContext = hubContext;
        }

        public void Send(List<Message> messages)
        {
            // to do: something where chatStorage calls this method, then this
            // method uses _hubContext.Clients.All.SendAsync 
            // But, how do I even call Send()???
        }
    }
}

从根本上说,我只是不明白如何将所有内容连接起来。 SignalR 真是令人困惑。

我了解了简单的服务器集线器和客户端 JavaScript 关系是如何工作的。但是,然后使用依赖注入我不明白为什么

public ChatHub(IChatStorage chatStorage)
        {
            _chatStorage = chatStorage;
        }

有效。我没有更改任何代码,比如 new ChatHub(new IChatStorage)。微软的文档甚至说 SignalR 只调用默认的 Hub 构造函数。

在 Startup.cs 中似乎没有指定我想用新的聊天存储调用 ChatHub:

public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        services.AddSignalR();
        services.AddSingleton<IChatStorage, ChatStorage>();
        services.AddSingleton<ChatController>();
    }

  public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // omitted some default code

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
            endpoints.MapHub<ChatHub>("/chatHub");
        });
    }

所以第一个问题,它是如何工作的?它如何知道将参数传递给 ChatHub 构造函数?我了解 services.AddSingleton 部分,只是不了解它是如何“连接”的。

与控制器类相同。程序如何知道将 IHubContext 对象传递给它的构造函数?你在哪里指定的?

最后,您将如何进行此设置?当前我正在尝试从 ChatHub->chatStorage->ChatController->ChatHub 进行通信。为此,我试图在 chatStorage 中传递对 chatController 的引用。

不确定我在问什么是否清楚。如果有的话,我正在寻找关于这些概念如何协同工作的清晰解释,而不是我的代码的特定解决方案。

谢谢!

【问题讨论】:

  • 查看official document,通过DI,我们可以在Startup.ConfigureServices方法中注册服务。使用这些服务时,使用服务接口并实现。不需要自己创建服务的实例,它是由 DI 容器创建的。 SignalR Hubs API 使您能够从服务器调用连接的客户端上的方法。你可以检查What is a SignalR hub

标签: asp.net signalr asp.net-core-signalr


【解决方案1】:

所以第一个问题,它是如何工作的?它如何知道将参数传递给 ChatHub 构造函数?我了解 services.AddSingleton 部分,只是不了解它是如何“连接”的。

当 SignalR 实例化您的集线器实例时(框架对此进行控制,而您没有),它将解析集线器构造函数中指定的任何依赖项。这是 dependency injection system 的一部分,它是 .NET 的一部分(如 cmets 中所述)。

与控制器类相同。程序如何知道将 IHubContext 对象传递给它的构造函数?你在哪里指定的?

同样的想法,但您不必连接 IHubContext,AddSignalR 就是这样做的。

最后,您将如何进行此设置?当前我正在尝试从 ChatHub->chatStorage->ChatController->ChatHub 进行通信。为此,我试图在 chatStorage 中传递对 chatController 的引用。

我不太清楚您希望客户端和服务器之间的交互与集线器和控制器的交互是什么。

我想要实现的是,在聊天应用程序中:将消息存储在 Hub 之外,以便每次用户加入聊天时,他们都可以看到在加入之前发送的所有消息。

回到最初的陈述,我可以问一些澄清问题:

  • 当用户在聊天室中写消息时,您是调用集线器还是控制器操作 (REST API)?这将确定您需要在哪里注入 IChatStorage 类型。收到消息后,您会将消息存储在 IChatStorage 中。
  • 当用户加入聊天时,他们将调用服务器以检索所有消息。此调用将返回存储在 IChatStorage 中的消息。

假设您想将集线器用于一切,您将在集线器上公开方法来完成此操作。如果您想使用来自客户端的 REST API 调用,那么您将使用控制器。

【讨论】:

  • 感谢您的回答——当我写这个问题时,我肯定体验到了催款克鲁格效应。事实证明,在深入了解 SignalR 之前了解什么是 Asp.net 核心和 MVC 会有所帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-01
相关资源
最近更新 更多