[英]Is there a difference when registering an IHostedService in .NET Core 3.+ in the startup.cs ConfigureServices or in program.cs Main method?
I'm playing around with trying to use IHostedServices in a 3.1 .NET Core web application.我正在尝试在 3.1 .NET Core web 应用程序中使用 IHostedServices。
I can see that I can register them in 2 different places:我可以看到我可以在 2 个不同的地方注册它们:
program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureServices(services =>
{
services.AddHostedService<BackgroundServiceA>();
services.AddHostedService<BackgroundServiceB>();
});
or in the ConfigureServices
method in startup.cs
或在startup.cs
的ConfigureServices
方法中
public void ConfigureServices(IServiceCollection services)
{
services.AddHostedService<BackgroundServiceA>();
}
I'm under the impression that both of these are identical.我的印象是这两者是相同的。 And if they are, does one override the other, if both exist?如果它们是,如果两者都存在,是否会覆盖另一个?
I'm under the impression that both of these are identical.我的印象是这两者是相同的。
Yes, both approaches inject a delegate into the logic used to build an IServiceProvider
.是的,这两种方法都将委托注入到用于构建IServiceProvider
的逻辑中。 Whether you do this via the IHostBuilder
or the Startup
class, the result is the same.无论您是通过IHostBuilder
还是Startup
class 执行此操作,结果都是一样的。
Does one override the other, if both exist?如果两者都存在,是否会覆盖另一个?
The answer to this depends on two things:这个问题的答案取决于两件事:
To make it easier to explain, here's the code copied from your question:为了更容易解释,这是从您的问题中复制的代码:
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>(); }
This shows an order that goes like this:这显示了这样的顺序:
Startup.ConfigureServices
, because ConfigureWebHostDefaults
is called first. Startup.ConfigureServices
,因为首先调用ConfigureWebHostDefaults
。IHostBuilder.ConfigureServices
This means the registration in your Startup
class runs first;这意味着您的Startup
class 中的注册首先运行; followed by the registration performed via IHostBuilder.ConfigureServices
in the Program
class.然后通过Program
IHostBuilder.ConfigureServices
中的 IHostBuilder.ConfigureServices 执行注册。
If you switch the order of those two calls, you also switch the order of the registrations:如果你切换这两个调用的顺序,你也会切换注册的顺序:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<BackgroundServiceA>();
services.AddHostedService<BackgroundServiceB>();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
With this change, the registration performed via IHostBuilder.ConfigureServices
runs first.通过此更改,首先运行通过IHostBuilder.ConfigureServices
执行的注册。
AddHostedService
uses TryAddEnumerable
behind the scenes. AddHostedService
在幕后使用TryAddEnumerable
。 If TryAddEnumerable
is called with a TService
to TImplementation
pair that already exists in the service collection, it's ignored.如果TryAddEnumerable
使用已存在于服务集合中的TService
到TImplementation
对来调用,则会被忽略。 Consider the following example, slightly adapted from the code in your question:考虑以下示例,稍微改编自您问题中的代码:
services.AddHostedService<BackgroundServiceA>();
services.AddHostedService<BackgroundServiceA>();
services.AddHostedService<BackgroundServiceB>();
The first call to add BackgroundServiceA
succeeds, registering BackgroundServiceA
against the IHostedService
interface.添加BackgroundServiceA
的第一次调用成功,将BackgroundServiceA
注册到IHostedService
接口。 The second time it's called, nothing happens, because this pair has already been registered.第二次调用时,什么也没有发生,因为这对已经注册了。
The first call to add BackgroundServiceB
also succeeds.添加BackgroundServiceB
的第一次调用也成功。 Although this is using the same interface, IHostedService
, it's a different implementation that's being registered, and so it's a different pair.尽管这是使用相同的接口IHostedService
,但它是一个不同的实现,正在注册,因此它是不同的对。
All of this means that the registration in your Startup.ConfigureServices
is the one that will be used.所有这一切都意味着您的Startup.ConfigureServices
中的注册将被使用。 This is because it runs first and because later registration ends up as a no-op.这是因为它首先运行并且因为后来的注册最终成为无操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.