回到.net core 2,我创建了一个具有自定义属性的托管服务,例如:
public class MyService : BackgroundService
{
public bool IsRunning {get;set;}
...
我可以在startup.cs中进行设置,例如:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IHostedService,HostedServices.MyService>();
...
然后我可以在剃刀页面的其他地方引用它,例如:
public class IndexModel : PageModel
{
private readonly IHostedService _mySrv;
public IndexModel(IHostedService mySrv) => _mySrv = mySrv;
[BindProperty]
public bool IsRunning { get; set; }
public void OnGet() => IsRunning = ((HostedServices.MyService)_mySrv).IsRunning;
}
现在我已经升级到.net core 3,我的启动已更改为:
services.AddHostedService<HostedServices.MyService>();
但是我在IndexModel中的DI参考不再给我MyService了,它给了我一个GenericWebHostService类型的对象,我不知道如何从中获取我的自定义MyService。在IndexModel中将'IHostedService'更改为'MyService'也不起作用,我收到“无法解析服务”错误。
如何从依赖项注入取回MyService的实例?
在2.2中,您主要是偶然地进行设置。每当您针对一个服务注册多个实现时,最后注册的将是“获胜”的实现。例如,使用以下代码:
services.AddSingleton<IHostedService, HostedService1>();
services.AddSingleton<IHostedService, HostedService2>();
// ...
public IndexModel(IHostedServie hostedService) { }
[注入到IHostedService
中的IndexModel
的实现是HostedService2
;最后一次注册。如果将IndexModel
更新为IEnumerable<IHostedService>
,它将按注册顺序获得both实现:
public IndexModel(IEnumerable<IHostedService> hostedServices) { }
[当我说“偶然”时,我是说在您的示例中,[[only HostedServices.MyService
被注册,因此它也是最后注册的,因此它“获胜”。]]在3.0中,当使用Generic Host时,IHostedService
,GenericWebHostService
的实现处理Web请求的处理。这给您带来了问题,因为GenericWebHostService
被注册为[[after
HostedServices.MyService
。我希望现在很清楚,这就是您在IHostedService
中请求的IndexModel
超出预期的原因。就解决方案而言,我建议执行两次注册:
services.AddSingleton<HostedServices.MyService>();
services.AddHostedService(sp => sp.GetRequiredService<HostedServices.MyService>());
然后,更新您的IndexModel
以要求您的特定实现:
public IndexModel(HostedServices.MyService myService) { }
这使您可以定位
IHostedService
的特定实现。它针对两种不同的服务类型进行了两次注册,但是只创建了一个实例。