回到.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的实例?
答案 0 :(得分:5)
在2.2中,您所做的设置大部分是偶然的。每当您针对一个服务注册多个实现时,最后注册的将是“获胜”的实现。例如,使用以下代码:
services.AddSingleton<IHostedService, HostedService1>();
services.AddSingleton<IHostedService, HostedService2>();
// ...
public IndexModel(IHostedServie hostedService) { }
注入到IHostedService
中的IndexModel
的实现是HostedService2
;最后一次注册。如果将IndexModel
更新为采用IEnumerable<IHostedService>
,则它将按注册顺序得到两个实现:
public IndexModel(IEnumerable<IHostedService> hostedServices) { }
当我说“偶然”时,我的意思是在您的示例中,只有 HostedServices.MyService
被注册,因此它也是最后一次注册,因此“获胜”。
在3.0中,使用Generic Host时,IHostedService
,GenericWebHostService
的实现处理Web请求。这给您带来了问题,因为GenericWebHostService
是在{em>之后{em> HostedServices.MyService
注册的。我希望现在很清楚,这就是您在IHostedService
中请求的IndexModel
超出预期的原因。
关于解决方案,我建议执行两次注册:
services.AddSingleton<HostedServices.MyService>();
services.AddHostedService(sp => sp.GetRequiredService<HostedServices.MyService>());
然后,更新您的IndexModel
以要求您执行特定的操作:
public IndexModel(HostedServices.MyService myService) { }
这使您可以定位IHostedService
的特定实现。它针对两种不同的服务类型进行了两次注册,但是只创建了一个实例。