从我的应用程序的其他部分访问信号器集线器

Posted

技术标签:

【中文标题】从我的应用程序的其他部分访问信号器集线器【英文标题】:Access to signalr hub from other part of my application 【发布时间】:2021-10-06 07:27:48 【问题描述】:

我正在编写一个 blazor 服务器 Web 应用程序。

我已经编写了这个非常基本的信号器集线器:

using Microsoft.AspNetCore.SignalR;

public class MyHub: Hub

   public override Task OnConnectedAsync()
   
      ...
      return base.OnConnectedAsync();
   

   public Task my_function()
   
      ...
   
   ....

在这一步可以正常工作。

现在,我想从我的 blazor 应用程序的另一部分访问此中心:

public class AnotherClass

   private readonly IHubContext<MyHub> _hub;

   public AnotherClass(IHubContext<MyHub> hub)
   
      _hub = hub;
   

   ...
   
   public void another_function()
   
      _hub.Clients.All.SendAsync(...); // <- This line works fine
      (_hub as MyHub).my_function();   // <- Does not work
   

如您所见,我正在使用依赖注入来访问我的集线器对象。 我已经阅读了很多文档,包括微软的官方文档。 每个人都说我们必须在这种依赖注入中使用 IHubContext 类型。

所以 _hub 对象不知道 my_function 方法...

我尝试了很多东西:

将 _hub 投射到 MyHub 声明一个 IMyHub 接口并在依赖注入中使用 IMyHub 等

没有任何效果...

我的问题是:如何从 AnotherClass 对象调用 my_function ?

非常感谢

【问题讨论】:

【参考方案1】:

我是这样做的。

为您的集线器创建一个界面:

public interface IMyHub

    Task MyFunction(int parameter);

然后你的集线器实现这样的接口:

public class MyHub : Hub<IMyHub>

    public async Task MyFunction(int parameter)
    
        // do stuff
    

然后将集线器注入其他类,如下所示:

private readonly IHubContext<MyHub, IMyHub> _myHub;

您可以通过以下方式调用您的函数:

_myhub.Clients.All.MyFunction(someInt);

这是基于Strongly Typed Hubs 和Send Messages From Outside a Hub 文档。

添加到 IMyHUb 接口的函数不一定必须在 MyHub 类中有实现代码。例如,与

public interface IMyHub

    Task MyFunction(int parameter);
    Task MySecondFunction();

你可以在其他类中调用

_myhub.Clients.All.MySecondFunction();

在 MyHub 类中没有任何新代码。

【讨论】:

奇怪,是不是每个客户端都会调用MyFunction? 这和_hub.Clients.All.SendAsync没有什么不同...集线器会将消息发送给所有连接的客户端 您也可以调用Clients.GroupClients.AllExceptClients.User,就像使用弱类型集线器一样。 事实上我想把逻辑放在集线器中,这是我想决定是否为一组、所有客户端等发送消息的地方。 在集线器类的调用函数中,您仍然可以访问客户端和组等,并且可以调用您想要的任何部分。【参考方案2】:

如何从 AnotherClass 对象调用 my_function ?

你不能。仅在响应客户端调用时调用集线器。无法手动调用 hub 方法。

如果您想在集线器内部和集线器外部运行逻辑,则需要重构代码,使其成为集线器和 AnotherClass 可以访问的某个共享类。

【讨论】:

是的,集线器是在客户端调用的上下文中设计的,因此它直接与特定客户端相关联。如果可以从任何地方任意调用集线器方法,您就会丢失有关客户端调用集线器方法的信息。这对于了解 connectionId、访问 Context.Items 以进行连接特定存储、Clients.Caller.SendAsync() 等非常有用。 这是错误的我有一个从微服务后端调用客户端的应用程序。你注入一个 IHubContext 调用客户端不同于从控制器等类手动调用集线器方法。我所说的一切都不反对从中心外致电客户。

以上是关于从我的应用程序的其他部分访问信号器集线器的主要内容,如果未能解决你的问题,请参考以下文章

如何使用信号器允许 cors

使用 Blazor 向其他浏览器发送通知

如何获取从我的 iOS 应用程序中的一个信号控制台发送的其他数据?

在信号器集线器类上设置 [Authorize] 属性仅在连接到集线器时有效,而不是在集线器上的每个方法之前(ASP.NET Core 2.2)

CCNA学习笔记:网络设备

类库中的 SignalR 集线器类