ASP.NET Core框架为我们提供了两个定义明确的初始化位置:1 Startup.ConfigureServices().注册DI服务的Startup.Configure()方法2. 中间件管道的配置方法
但是,其他针对我的Web应用程序的初始化步骤又如何呢?它们应该去哪儿,特别是如果它们需要注入依赖项时?
例如,我需要根据配置文件appsettings.json中指定的连接字符串初始化数据库ORM。因此,此初始化代码依赖于IConfiguration可能在注册过程中注册到DI容器中的其他自定义服务Startup.ConfigureServices()
因此,根据这些文章的建议:
https://odetocode.com/blogs/scott/archive/2019/02/14/net-core-opinion-7-startup-task.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;
}
}
Run Code Online (Sandbox Code Playgroud)
此扩展方法的用法如下所示:
CreateWebHostBuilder(args)
.Build()
.SomeExtension()
.Run();
Run Code Online (Sandbox Code Playgroud)
如果您需要的async版本SomeExtension,则可以拆分上面的链接和await扩展方法。可能是这样的:
public static async Task SomeExtensionAsync(this IWebHost webHost)
{
var config = webHost.Services.GetService<IConfiguration>();
// Your initialisation code here with awaits.
// ...
}
Run Code Online (Sandbox Code Playgroud)
用法看起来像这样:
public static async Task Main(string[] args)
{
var webHost = CreateWebHostBuilder(args)
.Build();
await webHost.SomeExtensionAsync();
webHost.Run();
}
Run Code Online (Sandbox Code Playgroud)
另外,我可以确定
Startup.ConfigureServices()在注册所有依赖项之后,将执行此代码吗?
使用我上面概述的方法,这里的答案是肯定的。
请注意,它IWebHost.Services代表root IServiceProvider,它将不支持解析作用域的实例。IConfiguration是单例,因此这不是问题,但是如果您具有范围内的依赖项,则需要在扩展方法内部创建一个显式范围。
您Program.cs的方法有以下代码Main:
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
Run Code Online (Sandbox Code Playgroud)
该Build()部分运行后,您就有了一个完全配置的主机。因此,您可以简单地执行如下操作:
var host = CreateWebHostBuilder(args).Build();
// do something with host
host.Run();
Run Code Online (Sandbox Code Playgroud)
主机有一个成员 ,Services它是 的实例IServiceProvider,因此您可以从中提取所需的任何服务,即
var config = host.Services.GetRequiredService<IConfiguration>();
Run Code Online (Sandbox Code Playgroud)
请记住,此时没有固有范围,因此如果您需要范围服务,则需要创建一个:
using (var scope = host.Services.CreateScope())
{
var myScopedService = scope.ServiceProvider.GetRequiredService<MyScopedService>();
// do something with myScopedService
}
Run Code Online (Sandbox Code Playgroud)