我有两个集线器,一个用于跟踪用户(chatHub),另一个集线器用于仪表板(dashHub)。
当新用户连接到网站时,它会触发跟踪用户ID和组的Server.Connect
方法。然后我想从ChatHub中调用DashHub.Update()
,以便所有破折号订阅者都可以获得推送给他们的新数据。
I have read this on the official documentation并且理解那里发生的事情很好,但我真的想调用那里有一些逻辑的DashHub.Update()
方法,而不仅仅是通过上下文发送消息。看看Stackoverflow和其他示例我已经得到了这个工作解决方案,但它看起来不正确。
ChatHub.cs
- 每当我需要将数据推送到仪表板时,都会调用UpdateDashboardClients()。它是私人的。
private void UpdateDashboardClients()
{
DashHub dh = new DashHub();
dh.SendNew();
}
DashHub.cs
- 这可以在dashbpaord客户端和我的解决方案中正常工作,以解决从Hub外部调用Context == null
问题,从我使用此插件的另一个Hub。
public void SendNew()
{
if (Context == null)
{
IHubContext contextDashHub = GlobalHost.ConnectionManager.GetHubContext<DashHub>();
contextDashHub.Clients.Clients(<clients>).PushNew(<data>)
}
else
{
Clients.Clients(<clients>).PushNew(<data>);
}
}
我尝试使用强制转换将已解决的IHubContext contextDashHub
设置为this.Context
,但失败了,因为this.Context
的类型为HubCallerContext
。
如果我可以创建另一个获取上下文的构造函数,或者只是一个获取上下文的方法,并将其分配给很好的dashhub上下文。
我在服务器上阅读了一些关于代理的内容,但不确定它是如何工作的,如果它甚至是正确的方法。
这个“解决方法”现在适用于我,但它不是非常可重复使用,它重复代码,这使它非常臭。
我想我需要以某种方式从ChatHub中使用DI(类似于获取上下文)才能正确地执行此操作,但我在DI仍然相当新,并且不确定如何做到这一点。
有人可以提供正确的方法吗。
答案 0 :(得分:1)
正如您已经注意到的那样,您要做的不是正确的方法。您真的想要自己实例化集线器并在其上调用方法这一事实是错误的。中心实例的生命周期应置于SignalR运行时的控制之下。
你得到一个空的上下文是完全逻辑的,你不应该试图改变它,否则就没有意义。例如,如果您的集线器中的代码正在检查Caller
端点,那么即使从逻辑角度来看也是如此(在这种情况下没有调用者)。你永远不应该尝试这样的黑客攻击,因为你无法建立一个适合每种情况的上下文。
您应该检查一下您的架构,该架构将处理来自客户端的请求以及与直接源自服务器的广播相关的内容分开。将这些视为两种不同的责任并相应地构建您的代码。您可以基于IHubContext
为服务器端消息引入“广播服务”,例如,您可以通过将自己的上下文传递给它来从hubs方法调用此服务的代码。该服务不知道该呼叫是由客户端还是由服务器代码发起的,它可以重复使用而且没有重复。
DI可以帮助您保持此类代码的清洁,但并非绝对必要。它还取决于您的应用程序的大小,但如果它只是一堆类型,您可以采取一些快捷方式,仍然保持代码的控制。否则,来自SignalR的DI支持不难管理,阅读它并且你会发现它很容易。如果你使用DI,你可能让你的集线器接收一个广播服务的实例(总是相同的实例或总是新的?它可以双向工作,它取决于它是如何实现的)并在相应的方法调用中使用它,传递在每种情况的正确背景下。