5

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

4

1 回答 1

13

在 2.2 中,您使用的设置主要是偶然的。每当您针对服务注册多个实现时,最后注册的是“获胜”的那个。例如,采用以下代码:

services.AddSingleton<IHostedService, HostedService1>();
services.AddSingleton<IHostedService, HostedService2>();

// ...

public IndexModel(IHostedServie hostedService) { }

IHostedService注入的实现IndexModelHostedService2;最后注册。如果IndexModel要更新为采用IEnumerable<IHostedService>,它将获得两种实现,按注册顺序:

public IndexModel(IEnumerable<IHostedService> hostedServices) { }

当我说“偶然”时,我的意思是在您的示例中, HostedServices.MyService注册,因此它也是最后注册的,因此它“获胜”。

在 3.0 中,当使用Generic HostIHostedService时,, 的实现会GenericWebHostService处理 Web 请求。这给您带来了一个问题GenericWebHostService因为. 我希望现在很清楚,这就是您请求的不是您所期望的原因。 HostedServices.MyServiceIHostedServiceIndexModel

在解决方案方面,我建议执行两个注册:

services.AddSingleton<HostedServices.MyService>();
services.AddHostedService(sp => sp.GetRequiredService<HostedServices.MyService>());

然后,更新您IndexModel以要求您的具体实施:

public IndexModel(HostedServices.MyService myService) { }

这使您可以针对特定的IHostedService. 它针对两种不同的服务类型注册了两次,但只创建了一个实例。

于 2019-10-27T19:51:41.263 回答