【问题标题】:How to reference a hosted service in .Net Core 3?如何在 .Net Core 3 中引用托管服务?
【发布时间】:2019-10-28 04:04:07
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

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

    services.AddSingleton<IHostedService, HostedService1>();
    services.AddSingleton<IHostedService, HostedService2>();
    
    // ...
    
    public IndexModel(IHostedServie hostedService) { }
    

    注入到IndexModel 中的IHostedService 的实现是HostedService2;最后注册。如果要更新IndexModel 以采用IEnumerable&lt;IHostedService&gt;,它将获得两个 实现,按注册顺序:

    public IndexModel(IEnumerable<IHostedService> hostedServices) { }
    

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

    在 3.0 中,当使用 Generic Host 时,IHostedServiceGenericWebHostService 的实现处理 Web 请求。这给您带来了一个问题,因为GenericWebHostService 是在HostedServices.MyService 之后注册的。我希望现在很清楚,这就是您在IndexModel 中请求的IHostedService 不是您所期望的原因。

    就解决方案而言,我建议进行两次注册:

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

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

    public IndexModel(HostedServices.MyService myService) { }
    

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

    【讨论】:

    • @KirkLarkin 真的等吗?我在哪里可以找到这方面的证据,因为我不明白如果您只是将其添加为单例,那么服务上的StartAsyncStopAsync 会调用什么。 this answer 似乎也与您的说法相矛盾。
    • @Joelius 只要在IHostedService 接口后面注册,就可以正常工作。这实际上就是AddHostedService 所做的一切。我会挖出一个指向源代码的链接来证明它......
    • @Joelius Here you goHost 只是请求IEnumerable&lt;IHostedService&gt; 并在它们上调用StartAsync。您链接的答案只是说AddSingleton 没有指定该接口不起作用,这是正确的。我不是说有什么不同。这是我展示的将它们联系在一起的第二个注册。
    • 哦,这是值得了解的。文档中是否提到了这一点?我觉得很容易假设它可能不会做同样的事情(尽管这样做很聪明)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多