如何在.Net Core 3中引用托管服务?

时间:2019-10-27 17:07:16

标签: c# asp.net-core asp.net-core-3.0 asp.net-core-hosted-services

回到.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的实例?

1 个答案:

答案 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时,IHostedServiceGenericWebHostService的实现处理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的特定实现。它针对两种不同的服务类型进行了两次注册,但是只创建了一个实例。