在startup.cs ConfigureServices或program.cs Main方法中在.NET Core 3



我正在尝试在3.1.NET Core web应用程序中使用IHostedServices。

我可以看到我可以在两个不同的地方注册它们:

  • program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureServices(services =>
{
services.AddHostedService<BackgroundServiceA>();
services.AddHostedService<BackgroundServiceB>();
});

或者在startup.cs中的ConfigureServices方法中

public void ConfigureServices(IServiceCollection services)
{
services.AddHostedService<BackgroundServiceA>();
}

我的印象是这两者完全相同。如果两者都存在,其中一个会凌驾于另一个之上吗?

我觉得这两者完全相同。

是的,这两种方法都将委托注入用于构建IServiceProvider的逻辑中。无论是通过IHostBuilder还是Startup类执行此操作,结果都是相同的。

如果两者都存在,其中一个是否覆盖另一个?

这个问题的答案取决于两件事:

  1. 您注册代理的顺序
  2. 注册本身的详细信息

为了更容易解释,以下是从您的问题中复制的代码:

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureServices(services =>
{
services.AddHostedService<BackgroundServiceA>();
services.AddHostedService<BackgroundServiceB>();
});
public void ConfigureServices(IServiceCollection services)
{
services.AddHostedService<BackgroundServiceA>();
}

这显示了一个如下的订单:

  1. Startup.ConfigureServices,因为首先调用ConfigureWebHostDefaults
  2. IHostBuilder.ConfigureServices

这意味着Startup类中的注册首先运行;接着经由CCD_ 11在CCD_。

如果你切换这两个呼叫的顺序,你也会切换注册的顺序:

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<BackgroundServiceA>();
services.AddHostedService<BackgroundServiceB>();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

通过此更改,首先运行通过IHostBuilder.ConfigureServices执行的注册。

AddHostedService在幕后使用TryAddEnumerable。如果使用服务集合中已经存在的TServiceTImplementation对调用TryAddEnumerable,则会忽略它。考虑下面的例子,稍微改编自您问题中的代码:

services.AddHostedService<BackgroundServiceA>();
services.AddHostedService<BackgroundServiceA>();
services.AddHostedService<BackgroundServiceB>();

添加BackgroundServiceA的第一次调用成功,在IHostedService接口上注册BackgroundServiceA。第二次调用时,没有发生任何事情,因为这对已经注册。

添加BackgroundServiceB的第一次调用也成功。尽管这使用了相同的接口IHostedService,但它是一个正在注册的不同实现,因此它是一对不同的接口。

所有这些都意味着将使用Startup.ConfigureServices中的注册。这是因为它首先运行,因为以后的注册最终会成为no-op。

最新更新