【问题标题】:How to inject strongly typed signalR hub in a class [ASP CORE 2.2]如何在类中注入强类型 signalR 集线器 [ASP CORE 2.2]
【发布时间】:2020-04-09 03:28:12
【问题描述】:

我想在服务中注入我的强类型集线器,但我不喜欢 Microsoft 显示的示例中的某些内容 - https://docs.microsoft.com/en-us/aspnet/core/signalr/hubcontext?view=aspnetcore-2.2(注入强类型的 HubContext)

public class ChatController : Controller
{
    public IHubContext<ChatHub, IChatClient> _strongChatHubContext { get; }

    public ChatController(IHubContext<ChatHub, IChatClient> chatHubContext)
    {
        _strongChatHubContext = chatHubContext;
    }

    public async Task SendMessage(string message)
    {
        await _strongChatHubContext.Clients.All.ReceiveMessage(message);
    }
}

在此示例中,ChatHubChatController 耦合。

所以我想注入集线器本身 使用通用接口参数定义,并且不会在我的服务中定义它的具体实现。 这是示例代码

public interface IReportProcessingClient
{
    Task SendReportInfo(ReportProgressModel report);
}
public class ReportProcessingHub : Hub<IReportProcessingClient>
{
    public async Task SendMessage(ReportProgressModel report)
    {
        await Clients.All.SendReportInfo(report);
    }
}

 public class ReportInfoHostedService : IHostedService, IDisposable
 {
     private readonly Hub<IReportProcessingClient> _hub;
     private readonly IReportGenerationProgressService _reportService;

     public ReportInfoHostedService(Hub<IReportProcessingClient> hub, IReportGenerationProgressService reportService)
     {
         _hub = hub;
         _reportService = reportService;
     }

     public Task StartAsync(CancellationToken cancellationToken)
     {
         _reportService.SubscribeForChange(async x =>
         {
             await _hub.Clients.All.SendReportInfo(x);
         });

         return Task.CompletedTask;
     }

     public Task StopAsync(CancellationToken cancellationToken)
     {
         return Task.CompletedTask;
     }

     public void Dispose()
     {
     }
 }

这种方法显然需要在 Startup.cs 中额外注册集线器,因为它不被 Microsoft 提供的上下文 api 调用。

services.AddSingleton<Hub<IReportProcessingClient>, ReportProcessingHub>();
app.UseSignalR(route => {
      route.MapHub<ReportProcessingHub>("/reportProcessingHub");
});

在中心尝试向客户端发送消息之前,一切都已完成并正常工作。然后我得到了异常

_hub.Clients.All threw an exception of System.NullReferenceException: 'Object reference not set to an instance of an object.'

总结一下:

1.这是注入强类型集线器的正确方法吗?我做错了什么(例如,集线器在服务中的错误注册,app.UseSingleR 的错误使用)?

2。如果不是,正确的方法是什么?

注意: 我知道注入IHubContext&lt;Hub&lt;IReportProcessingClient&gt;&gt; 有很多更简单的方法,但这对我来说不是解决方案,因为我必须调用作为string 参数传递的集线器方法名称。

【问题讨论】:

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


    【解决方案1】:

    我想...并且在我的服务中不会定义它的具体实现

    1. 如果您不想公开具体的集线器实现,您至少应该公开基类接口。但是,由于集线器应该继承自 Hub 类,因此我们不能在此处使用接口。所以让我们创建一个公共基础集线器ReportProcessingHubBase 以及一个内部具体的ReportProcessingHub

      public abstract class ReportProcessingHubBase : Hub<IReportProcessingClient>
      {
          public abstract Task SendMessage(ReportProgressModel report);
      }
      
      // the concrete hub will NOT be exposed
      internal class ReportProcessingHub : ReportProcessingHubBase
      {
          public override async Task SendMessage(ReportProgressModel report)
          {
              await Clients.All.SendReportInfo(report);
          }
      }
      
    2. 确保你已经注册了两个相关的服务:

      services.AddScoped<ReportProcessingHubBase, ReportProcessingHub>();
      services.AddHostedService<ReportInfoHostedService>();
      
    3. 确保您正在映射 Base Hub最重要的!):
       endpoints.MapHub<ReportProcessingHubBase>("/report");
      
    4. 最后,你可以通过注入IHubContext&lt;ReportProcessingHubBase,IReportProcessingClient&gt; 来获得base hub:

      public class ReportInfoHostedService : IHostedService, IDisposable
      {
          private readonly IHubContext<ReportProcessingHubBase,IReportProcessingClient> _hub;
      
          public ReportInfoHostedService(IHubContext<ReportProcessingHubBase,IReportProcessingClient> hub)
          {
              _hub = hub;
          }
      
          ...
       }
      

      现在,您可以以强类型的方式调用 hub 方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-14
      • 2020-08-13
      相关资源
      最近更新 更多