从另一个对象中获取 SignalR Core 中的 Hub 上下文
Get Hub Context in SignalR Core from within another object
我正在使用 Microsoft.AspNetCore.SignalR
(最新版本)并希望从另一个不是 Controller
的对象中获取集线器上下文。在 "full" SignalR 中,我可以使用 GlobalHost.ConnectionManager.GetHubContext<MyCoolHub>();
我见过很多将 Microsoft.AspNetCore.SignalR.IHubContext<MyCoolHub>
作为参数添加到 Controller
的 Ctor 的示例,但没有其他示例(有效)。
预计到达时间:
所以,这就是我的工作。这是 hacky 吗?
public class MyHub : Hub
public static IHubContext<MyHub> GlobalContext { get; private set; }
public MyHub(IHubContext<MyHub> ctx){
GlobalContext = ctx;
}
}
那么我可以这样称呼它:
await MyHub.GlobalContext.Clients.All.InvokeAsync(...)
只需在调用方构造函数上设置 IHubContext<MyHub> hubContext
。
我建议使用 .net 核心默认 DI 容器机制,而不是创建静态 属性。
请参考How do I get a reference to a Hub?
public class MyHub : Hub
{
}
public class CallingSideClass
{
private readonly IHubContext<MyHub> _hubContext;
public CallingSideClass(IHubContext<MyHub> hubContext)
{
_hubContext = hubContext;
}
public async Task FooMethod(...)
{
await _hubContext.Clients.All.InvokeAsync(...);
}
}
public class Startup
{...
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
services.AddScoped<CallingSideClass>();
}
...
}
所以在查看 this example 接受的答案后,我不太明白他的意思,所以我尝试了一些东西,我想我明白了他在说什么。因此,对于将来遇到此问题的人,我想将该示例更改为一个完整的示例。
因此我们将创建一个 "Shared Methods",如示例所示:
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
namespace YouDontNeedToKnow.Core.Main.Hubs
{
internal class HubMethods<THub> where THub : Hub
{
private readonly IHubContext<THub> _hubContext;
public HubMethods(IHubContext<THub> hubContext)
{
_hubContext = hubContext;
}
public Task InvokeOnGroupAsync(string groupName, string method, params object[] args) =>
_hubContext.Clients.Group(groupName).InvokeAsync(method, args);
public Task InvokeOnAllAsync(string method, params object[] args) =>
_hubContext.Clients.All.InvokeAsync(method, args);
public Task AddConnectionIdToGroupAsync(string connectionId, string groupName) =>
_hubContext.Groups.AddAsync(connectionId, groupName);
// ...
}
}
然后,在您的 Hub
对象中,添加一个构造函数,如下所示:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
namespace YouDontNeedToKnow.Core.Main.Hubs
{
internal class MyHub : Hub
{
public static string HubName => "myHub";
private readonly HubMethods<MyHub> _hubMethods;
public PlayerServicesHub(HubMethods<MyHub> hubMethods)
{
_hubMethods = hubMethods;
}
public override Task OnConnectedAsync()
{
return base.OnConnectedAsync();
}
}
}
在您的 Startup.cs
中,您像这样注入共享 class:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<HubMethods<MyHub>>();
services.AddSignalR();
services.AddMvc();
}
这仍然像往常一样工作:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider sp)
{
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseSignalR(routes =>
{
routes.MapHub<MyHub>(MyHub.HubName);
});
app.UseMvc();
// This is just an example line of how you can get the hub with context:
var myHub = sp.GetService<HubMethods<MyHub>>();
}
我正在使用 Microsoft.AspNetCore.SignalR
(最新版本)并希望从另一个不是 Controller
的对象中获取集线器上下文。在 "full" SignalR 中,我可以使用 GlobalHost.ConnectionManager.GetHubContext<MyCoolHub>();
我见过很多将 Microsoft.AspNetCore.SignalR.IHubContext<MyCoolHub>
作为参数添加到 Controller
的 Ctor 的示例,但没有其他示例(有效)。
预计到达时间:
所以,这就是我的工作。这是 hacky 吗?
public class MyHub : Hub
public static IHubContext<MyHub> GlobalContext { get; private set; }
public MyHub(IHubContext<MyHub> ctx){
GlobalContext = ctx;
}
}
那么我可以这样称呼它:
await MyHub.GlobalContext.Clients.All.InvokeAsync(...)
只需在调用方构造函数上设置 IHubContext<MyHub> hubContext
。
我建议使用 .net 核心默认 DI 容器机制,而不是创建静态 属性。
请参考How do I get a reference to a Hub?
public class MyHub : Hub
{
}
public class CallingSideClass
{
private readonly IHubContext<MyHub> _hubContext;
public CallingSideClass(IHubContext<MyHub> hubContext)
{
_hubContext = hubContext;
}
public async Task FooMethod(...)
{
await _hubContext.Clients.All.InvokeAsync(...);
}
}
public class Startup
{...
public void ConfigureServices(IServiceCollection services)
{
services.AddSignalR();
services.AddScoped<CallingSideClass>();
}
...
}
所以在查看 this example 接受的答案后,我不太明白他的意思,所以我尝试了一些东西,我想我明白了他在说什么。因此,对于将来遇到此问题的人,我想将该示例更改为一个完整的示例。
因此我们将创建一个 "Shared Methods",如示例所示:
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
namespace YouDontNeedToKnow.Core.Main.Hubs
{
internal class HubMethods<THub> where THub : Hub
{
private readonly IHubContext<THub> _hubContext;
public HubMethods(IHubContext<THub> hubContext)
{
_hubContext = hubContext;
}
public Task InvokeOnGroupAsync(string groupName, string method, params object[] args) =>
_hubContext.Clients.Group(groupName).InvokeAsync(method, args);
public Task InvokeOnAllAsync(string method, params object[] args) =>
_hubContext.Clients.All.InvokeAsync(method, args);
public Task AddConnectionIdToGroupAsync(string connectionId, string groupName) =>
_hubContext.Groups.AddAsync(connectionId, groupName);
// ...
}
}
然后,在您的 Hub
对象中,添加一个构造函数,如下所示:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
namespace YouDontNeedToKnow.Core.Main.Hubs
{
internal class MyHub : Hub
{
public static string HubName => "myHub";
private readonly HubMethods<MyHub> _hubMethods;
public PlayerServicesHub(HubMethods<MyHub> hubMethods)
{
_hubMethods = hubMethods;
}
public override Task OnConnectedAsync()
{
return base.OnConnectedAsync();
}
}
}
在您的 Startup.cs
中,您像这样注入共享 class:
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<HubMethods<MyHub>>();
services.AddSignalR();
services.AddMvc();
}
这仍然像往常一样工作:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider sp)
{
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseSignalR(routes =>
{
routes.MapHub<MyHub>(MyHub.HubName);
});
app.UseMvc();
// This is just an example line of how you can get the hub with context:
var myHub = sp.GetService<HubMethods<MyHub>>();
}