我应该在 ASP.NET Core 中的什么位置执行自定义应用程序初始化步骤?



>ASP.NET 核心框架为我们提供了两个定义明确的初始化位置: 1. 注册DI服务的Startup.ConfigureServices()方法 2. 中间件流水线配置的Startup.Configure()方法

但是,特定于我的 Web 应用程序的其他初始化步骤呢?这些应该去哪里,特别是如果它们有需要注入的依赖项?

例如,我需要根据配置文件appsettings.json中指定的连接字符串初始化数据库ORM。因此,此初始化代码依赖于IConfiguration,也可能依赖于在Startup.ConfigureServices()期间注册到 DI 容器中的其他自定义服务

因此,根据这些文章中的建议:

  • https://odetocode.com/blogs/scott/archive/2019/02/14/net-core-opinion-7-startup-responsibilities.aspx

  • https://odetocode.com/blogs/scott/archive/2019/03/07/net-core-opinion-10-move-more-code-out-of.aspx

我尝试将初始化逻辑封装在单独的类中,然后为将执行此代码的IWebHostBuilder创建扩展方法,但是如何使框架将IConfiguration和其他自定义依赖项注入此扩展方法?另外,我能否确定此代码将在注册所有依赖项后Startup.ConfigureServices()执行?

是否有更好或推荐的方法来执行此类任务?

您可以为IWebHost添加扩展方法(而不是IWebHostBuilder),然后使用IWebHost.Services解析服务。下面是如何检索IConfiguration的示例:

public static class WebHostExtensions
{
public static IWebHost SomeExtension(this IWebHost webHost)
{
var config = webHost.Services.GetService<IConfiguration>();
// Your initialisation code here.
// ...
return webHost;
}
}

此扩展方法的用法如下所示:

CreateWebHostBuilder(args)
.Build()
.SomeExtension()
.Run();

如果您需要async版本的SomeExtension,您可以拆分上面的链接并await扩展方法。这可能是这样的:

public static async Task SomeExtensionAsync(this IWebHost webHost)
{
var config = webHost.Services.GetService<IConfiguration>();
// Your initialisation code here with awaits.
// ...
}

用法如下所示:

public static async Task Main(string[] args)
{
var webHost = CreateWebHostBuilder(args)
.Build();
await webHost.SomeExtensionAsync();
webHost.Run();
}

另外,我能否确定此代码将在注册所有依赖项后Startup.ConfigureServices()执行?

使用我上面概述的方法,这里的答案是肯定的。


请注意,IWebHost.Services表示IServiceProvider,不支持解析作用域实例IConfiguration是一个单一实例,所以这不是问题,但如果具有作用域依赖项,则需要在扩展方法中创建显式作用域。

Program.cs中,您的Main方法具有以下代码:

public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}

运行Build()部件后,您将拥有一个完全配置的主机。因此,您可以简单地执行以下操作:

var host = CreateWebHostBuilder(args).Build();
// do something with host
host.Run();

主机有一个成员Services,它是IServiceProvider的一个实例,因此您可以从中提取所需的任何服务,即

var config = host.Services.GetRequiredService<IConfiguration>();

请记住,此时没有固有的作用域,因此如果需要作用域服务,则需要创建一个:

using (var scope = host.Services.CreateScope())
{
var myScopedService = scope.ServiceProvider.GetRequiredService<MyScopedService>();
// do something with myScopedService
}

最新更新