如何从Singleton类访问Net Core Web API中的IHubContext

时间:2018-11-27 08:50:03

标签: c# asp.net-core signalr

ASP.NET CORE 2.1 WEB API

我有一个单例类,它是在API需要并且一直运行时在Startup.cs中启动的tcpip客户端(TcpIpSerrvice)。我无法弄清楚如何从此单例访问IHubContext以便能够通过SignalR将tcp数据发送到Web前端。

我试图通过sigleton类中的静态Action属性来触发此操作,但是当在Hub中触发此操作时,Hub已被处理,并且我得到(System.ObjectDisposedException:'无法访问已处理的对象。')< / em>

在单例课程中

public static Action<string> DataArrived { get; set; }

以及在中心地带时

TcpIpService.DataArrived = new Action<string>(MessageFromPlcReceived);

我知道可以将其注入到Controllers或服务中,但是我需要它才能从其他地方访问它。

我知道GlobalHost在新的SignalR中不可用,并且IHubContext很容易注入,但是(至少到目前为止)对于在Startup.cs中单独实例化的单例类,这是行不通的(至少到目前为止)。

任何想法如何做到这一点?

通过SignalR GitHub存储库后,我发现这样做的丑陋方式。我可以在Startup.cs的Configure方法中执行此操作:

TcpIpService.HubContext = app.ApplicationServices.GetRequiredService<IHubContext<VcHub>>();

只是创建旧的GlobalHost之前所做的。尽管这很丑,但到目前为止我找不到更好的解决方案。有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

我没有找到合适的方法来解决此问题,因此我将 TcpService 重写为 IHostedService ,然后可以在 Startup中注册它。 cs 并将 IHubContext 注入服务并从所需的类访问上下文。

var closeButton = $("span.close");    
window.onload = function () {
    history.pushState("jibberish", null, null);
    window.onpopstate = function () {
        if (closeButton.is(":visible")) {
            closeButton.click();
        // Handle the back (or forward) buttons here
        // Will NOT handle refresh, use onbeforeunload for this.
            history.pushState('newjibberish', null, null);
            console.log('returned');
        } else {
            console.log('manually going back to previous');
            history.go("jibberish");
            history.go(-1);
        }
    };
};

在Startup.cs

...
using Microsoft.Extensions.Hosting;
...

public class HostedTcpIpService : IHostedService, IDisposable
{
    #region Declaration(s)

    private readonly ILogger<HostedTcpIpService> logger;
    private readonly IHubContext<VcHub> hubContext;

    #endregion

    #region Constructor

    public HostedTcpIpService(
        ILogger<HostedTcpIpService> logger,
        IHubContext<VcHub> hubContext)
    {
        this.logger = logger;
        this.hubContext = hubContext;
    } 

    #endregion

    #region IDisposable

    public void Dispose()
    {
        // disposing
    } 

    #endregion

    #region IHostedService

    public Task StartAsync(CancellationToken cancellationToken)
    {
        // Start Tcp connection
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        // Stop Tcp connection
    }

    #endregion

    private void OnTcpMessageReceived(string tcpMessage) 
    {
        // injected hubContext ...
        // broadcast to signalR clients
        this.hubContext.Clients.All.SendAsync("broadcastMessage", tcpMessage);
    }
}