我正在尝试在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
类执行此操作,结果都是相同的。
如果两者都存在,其中一个是否覆盖另一个?
这个问题的答案取决于两件事:
- 您注册代理的顺序
- 注册本身的详细信息
为了更容易解释,以下是从您的问题中复制的代码:
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>(); }
这显示了一个如下的订单:
Startup.ConfigureServices
,因为首先调用ConfigureWebHostDefaults
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
。如果使用服务集合中已经存在的TService
到TImplementation
对调用TryAddEnumerable
,则会忽略它。考虑下面的例子,稍微改编自您问题中的代码:
services.AddHostedService<BackgroundServiceA>();
services.AddHostedService<BackgroundServiceA>();
services.AddHostedService<BackgroundServiceB>();
添加BackgroundServiceA
的第一次调用成功,在IHostedService
接口上注册BackgroundServiceA
。第二次调用时,没有发生任何事情,因为这对已经注册。
添加BackgroundServiceB
的第一次调用也成功。尽管这使用了相同的接口IHostedService
,但它是一个正在注册的不同实现,因此它是一对不同的接口。
所有这些都意味着将使用Startup.ConfigureServices
中的注册。这是因为它首先运行和,因为以后的注册最终会成为no-op。