无需构造函数注入的Access SignalR集线器 [英] Access SignalR Hub without Constructor Injection
问题描述
使用AspNetCore.SignalR(1.0.0 Preview1-final)和AspNetCore.All(2.0.6),如何在服务器代码中的集线器上调用方法,而该方法不是直接在Controller中而是在一个类中不能通过依赖注入来实现?
With AspNetCore.SignalR (1.0.0 preview1-final) and AspNetCore.All (2.0.6), how can I invoke a method on a hub in server code that is not directly in a Controller and is in a class that cannot be made via Dependency Injection?
大多数示例都假定服务器代码在Controller中,并且应该通过将由DI创建的类中的可注入参数询问"集线器.
Most examples assume the server code is in a Controller and should 'ask' for the hub via an injectable parameter in a class that will created by DI.
我希望能够在任何时候以未注入的代码从服务器代码中调用集线器的方法.旧的SignalR具有启用此方法的GlobalHost.基本上,我需要将集线器设置为全局单例.
I want to be able to call the hub's method from server code at any time, in code that is not injected. The old SignalR had a GlobalHost that enabled this approach. Basically, I need the hub to be a global singleton.
现在,一切似乎都依赖于依赖注入,这引入了我不想要的依赖!
Now, everything seems to be dependent on using Dependency Injection, which is introducing a dependency that I don't want!
我已经在很多地方看到了这个请求,但是还没有找到可行的解决方案.
I've seen this request voiced in a number of places, but haven't found a working solution.
修改
更清楚地说,我需要做的就是以后能够访问我在Startup
类的Configure
例程中注册的集线器:
To be more clear, all I need is to be able to later access the hubs that I've registered in the Configure
routine of the Startup
class:
app.UseSignalR(routes =>
{
routes.MapHub<PublicHubCore>("/public");
routes.MapHub<AnalyzeHubCore>("/analyze");
routes.MapHub<ImportHubCore>("/import");
routes.MapHub<MainHubCore>("/main");
routes.MapHub<FrontDeskHubCore>("/frontdesk");
routes.MapHub<RollCallHubCore>("/rollcall");
// etc.
// etc.
});
如果我这样注册他们:
services.AddSingleton<IPublicHub, PublicHubCore>();
它不起作用,因为我返回了未启动的集线器.
it doesn't work, since I get back an uninitiated Hub.
推荐答案
感谢那些提供帮助的人.这就是我现在要结束的事情...
Thanks to those who helped with this. Here's what I've ended up on for now...
在我的项目中,我可以从任何地方调用这样的内容:
In my project, I can call something like this from anywhere:
Startup.GetService<IMyHubHelper>().SendOutAlert(2);
要完成这项工作,我在Startup.cs
中有以下多余的行,以便于我轻松访问依赖项注入服务提供程序(与SignalR不相关):
To make this work, I have these extra lines in Startup.cs
to give me easy access to the dependency injection service provider (unrelated to SignalR):
public static IServiceProvider ServiceProvider { get; private set; }
public static T GetService<T>() { return ServiceProvider.GetRequiredService<T>(); }
public void Configure(IServiceProvider serviceProvider){
ServiceProvider = serviceProvider;
}
正常的SignalR设置要求:
The normal SignalR setup calls for:
public void Configure(IApplicationBuilder app){
// merge with existing Configure routine
app.UseSignalR(routes =>
{
routes.MapHub<MyHub>("/myHub");
});
}
我不希望我的所有代码都必须直接调用原始SignalR方法,因此我为每个方法创建了一个帮助器类.我在DI容器中注册了该助手:
I don't want all my code to have to invoke the raw SignalR methods directly so I make a helper class for each. I register that helper in the DI container:
public void ConfigureServices(IServiceCollection services){
services.AddSingleton<IMyHubHelper, MyHubHelper>();
}
这是我制作MyHub类集的方式:
Here's how I made the MyHub set of classes:
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
public class MyHub : Hub { }
public interface IMyHubHelper
{
void SendOutAlert(int alertNumber);
}
public class MyHubHelper : IMyHubHelper
{
public IHubContext<MyHub> HubContext { get; }
public MyHubHelper(IHubContext<MyHub> hubContext)
{
HubContext = hubContext;
}
public void SendOutAlert(int alertNumber)
{
// do anything you want to do here, this is just an example
var msg = Startup.GetService<IAlertGenerator>(alertNumber)
HubContext.Clients.All.SendAsync("serverAlert", alertNumber, msg);
}
}
这篇关于无需构造函数注入的Access SignalR集线器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!