【发布时间】:2019-02-01 20:31:38
【问题描述】:
详情
我尝试在 ASP.NET 2.1 中使用推荐的IHostedService 接口创建后台处理结构。我注册服务如下:
services.AddSingleton<AbstractProcessQueue<AbstractImportProcess>>();
services.AddHostedService<AbstractBackgroundProcessService<AbstractImportProcess>>();
services.AddSignalR();
AbstractProcessQueue 只是对可以入队和出队的进程BlockingCollection 的包装。 AbstractBackgroundProcessService 实现了IHostedService 接口,并在队列中查找它可以启动的新进程。
现在,当我在SignalR 集线器内尝试通过Dependency Injection 机制获取对后台处理服务的引用时,麻烦就开始了。我尝试了以下解决方案,但似乎都没有按预期工作:
选项 1:
public HubImportClient(IServiceProvider provider)
{
//This returns null.
var service = provider.GetService<AbstractBackgroundProcessService<AbstractImportProcess>>();
}
选项 2:
public HubImportClient(IServiceProvider provider)
{
//This returns null.
var service = (AbstractBackgroundProcessService<AbstractImportProcess>) provider.GetService(typeof(AbstractBackgroundProcessService<AbstractImportProcess>>));
}
选项 3:
public HubImportClient(IServiceProvider provider)
{
//This throws an exception, because the service is missing.
var service = provider.GetRequiredService<AbstractBackgroundProcessService<AbstractImportProcess>>();
}
选项 4:
public HubImportClient(IServiceProvider provider)
{
//This throws an exception, because the service is missing.
var service = (AbstractBackgroundProcessService<AbstractImportProcess>) provider.GetRequiredService(typeof(AbstractBackgroundProcessService<AbstractImportProcess>);
}
选项 5:
public HubImportClient(IServiceProvider provider)
{
//This returns a correct service, but prevents me from adding additional AbstractBackgroundProcessService implementations with different type parameters.
//Additionally, it seems like this reference was newly created, and not the instance that was created on application startup (i.e. the hash codes are different, and the constructor is called an additional time).
var service = provider.GetService<IHostedService>();
if(service is AbstractBackgroundProcessService<AbstractProcessService>)
{ this.Service = (AbstractBackgroundProcessService<AbstractProcessService>) service;}
}
选项 6:
public HubImportClient(IServiceProvider provider)
{
//This works similarly to the previous option, and allows multiple implementations, but the constructor is still called twice and the instances thus differ.
AbstractBackgroundProcessService<AbstractImportProcess> service = null;
foreach(IHostedService service in provider.GetServices<IHostedService>())
{
if(service is AbstractBackgroundProcessService<AbstractImportProcess>)
{
service = (AbstractBackgroundProcessService<AbstractImportProcess>) service;
break;
}
}
}
选项 7:
public HubImportClient(IServiceProvider provider)
{
//This just skips the for each loop all together, because no such services could be found.
AbstractBackgroundProcessService<AbstractImportProcess> service = null;
foreach(AbstractBackgroundProcessService<AbstractImportProcess> current in provider.GetServices<AbstractBackgroundProcessService<AbstractImportProcess> >())
{
service = current;
break;
}
}
选项 8:
//This works, but prevents multiple implementations again.
public HubImportClient(IHostedService service)
{
this.Service = service;
}
选项 9:
//This does not work again.
public HubImportClient(AbstractBackgroundProcessService<AbstractImportProcess> service)
{
this.Service = service;
}
问题
那么我的问题仍然存在:我应该如何获得对 IHostedService 实现的引用,以便:
(a):我可以注入服务的多个实例,它们的区别仅在于它们的类型参数(例如,AbstractImportProcesses 的托管服务以及 AbstractExportProcesses 的托管服务)
(b):对于该特定类型参数,IHostedService 只有一个实例。
提前感谢您的帮助!
【问题讨论】:
-
为什么直接需要服务实例?这是非典型的。您需要做的只是注册
IHostedService实现。 ASP.NET Core 负责实例化和运行它。 -
@ChrisPratt 我希望获得我的 HostedService 的已配置活动实例的状态,这将是启动/停止的全部目的,我的作用域服务接收由我的 HostedService 引导的热实例.
-
最后我只是向我的 HostedService 添加了一个静态属性,以便在 DI 中注册。
标签: c# asp.net asp.net-core dependency-injection asp.net-core-2.1