如何对集线器进行 SignalR 外部引用而不执行循环引用?
How do I make a SignalR external reference to hub and not perform circular reference?
所以,我正在尝试创建一个示例,其中包含以下 components/features:
- 从 Windows 服务
自托管的 hangfire 服务器 OWIN
- 作业完成时的 SignalR 通知
我可以让任务排队并执行,但我很难弄清楚如何通知客户(目前都是,直到我让它运行良好)task/job已完成。
我当前的问题是我希望 SignalR 集线器位于 "core" 库 SampleCore, but I don't see how to "register it" when starting the webapp SampleWeb. One way I've gotten around that is to create a hub class NotificationHubProxy 中,它继承了实际的集线器并且适用于简单的东西(从一个客户端发送消息到全部)。
在 NotifyTaskComplete 中,我相信我可以获取集线器上下文,然后像这样发送消息:
private void NotifyTaskComplete(int taskId)
{
try
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
if (hubContext != null)
{
hubContext.Clients.All.sendMessage(string.Format("Task {0} completed.", taskId));
}
}
catch (Exception ex)
{
}
}
但是,如果 NotificationHubProxy 是 class,我不能这样做,因为它是 SampleWeb 库的一部分并且从 SampleCore 引用它会导致循环引用。
我知道主要问题是外部组件中的集线器,但我终其一生都找不到使用 SignalR 或 MVC5 或以这种特定方式设置的相关示例。
有什么想法吗?
因此,解决方案是执行以下两件事:
我必须使用 SampleCore 程序集中的 SignalR .NET 客户端创建一个 HubConnection,为 "NotificationHub" 创建一个 HubProxy 并使用它来调用 "SendMessage" 方法- 像这样:
private void NotifyTaskComplete(string hostUrl, int taskId)
{
var hubConnection = new HubConnection(hostUrl);
var hub = hubConnection.CreateHubProxy("NotificationHub");
hubConnection.Start().Wait();
hub.Invoke("SendMessage", taskId.ToString()).Wait();
}
但是,作为创建 HubConnection 的一部分 - 我需要知道 OWIN 实例的 url。我决定将那个参数传递给任务,像这样检索它:
private string GetHostAddress()
{
var request = this.HttpContext.Request;
return string.Format("{0}://{1}", request.Url.Scheme, request.Url.Authority);
}
将集线器置于外部程序集中的解决方案是需要在设置 SignalR 路由之前加载程序集,如下所示:
AppDomain.CurrentDomain.Load(typeof(SampleCore.NotificationHub).Assembly.FullName);
app.MapSignalR();
这部分的解决方案来自 here。
所以,我正在尝试创建一个示例,其中包含以下 components/features:
- 从 Windows 服务 自托管的 hangfire 服务器 OWIN
- 作业完成时的 SignalR 通知
我可以让任务排队并执行,但我很难弄清楚如何通知客户(目前都是,直到我让它运行良好)task/job已完成。
我当前的问题是我希望 SignalR 集线器位于 "core" 库 SampleCore, but I don't see how to "register it" when starting the webapp SampleWeb. One way I've gotten around that is to create a hub class NotificationHubProxy 中,它继承了实际的集线器并且适用于简单的东西(从一个客户端发送消息到全部)。
在 NotifyTaskComplete 中,我相信我可以获取集线器上下文,然后像这样发送消息:
private void NotifyTaskComplete(int taskId)
{
try
{
var hubContext = GlobalHost.ConnectionManager.GetHubContext<NotificationHub>();
if (hubContext != null)
{
hubContext.Clients.All.sendMessage(string.Format("Task {0} completed.", taskId));
}
}
catch (Exception ex)
{
}
}
但是,如果 NotificationHubProxy 是 class,我不能这样做,因为它是 SampleWeb 库的一部分并且从 SampleCore 引用它会导致循环引用。
我知道主要问题是外部组件中的集线器,但我终其一生都找不到使用 SignalR 或 MVC5 或以这种特定方式设置的相关示例。
有什么想法吗?
因此,解决方案是执行以下两件事:
我必须使用 SampleCore 程序集中的 SignalR .NET 客户端创建一个 HubConnection,为 "NotificationHub" 创建一个 HubProxy 并使用它来调用 "SendMessage" 方法- 像这样:
private void NotifyTaskComplete(string hostUrl, int taskId) { var hubConnection = new HubConnection(hostUrl); var hub = hubConnection.CreateHubProxy("NotificationHub"); hubConnection.Start().Wait(); hub.Invoke("SendMessage", taskId.ToString()).Wait(); }
但是,作为创建 HubConnection 的一部分 - 我需要知道 OWIN 实例的 url。我决定将那个参数传递给任务,像这样检索它:
private string GetHostAddress()
{
var request = this.HttpContext.Request;
return string.Format("{0}://{1}", request.Url.Scheme, request.Url.Authority);
}
将集线器置于外部程序集中的解决方案是需要在设置 SignalR 路由之前加载程序集,如下所示:
AppDomain.CurrentDomain.Load(typeof(SampleCore.NotificationHub).Assembly.FullName); app.MapSignalR();
这部分的解决方案来自 here。