如何调整ASP.NET Core启动顺序 使Startup.ConfigureServices优先于HostingStartup执行
解决方案
ASP.NET Core 内置的启动逻辑中,通过ASPNETCORE_HOSTINGSTARTUPASSEMBLIES自动加载的IHostingStartup实现,其服务注册逻辑默认会优先于主程序Startup.ConfigureServices执行,无法直接修改内置执行顺序,可通过以下两种方案实现需求:
方案1:调整代码结构(推荐,无额外性能开销)
直接将原来Startup.ConfigureServices中的逻辑提前到Program.cs的服务注册阶段,该阶段的逻辑会先于所有IHostingStartup的逻辑执行,完全符合要求:
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) // 提前注册你的自定义服务 .ConfigureServices(services => { // 此处粘贴原来Startup.ConfigureServices中的所有DI注册逻辑 services.AddControllers(); // ...其他原有注册代码 }) .ConfigureWebHostDefaults(webBuilder => { // 保留原有Startup配置、环境变量配置无需修改 webBuilder.UseStartup<Startup>(); });
此时执行顺序为:你的自定义服务注册 → MyCustomStartup1逻辑 → MyCustomStartup2逻辑 → Startup.ConfigureServices,完全满足需求。
方案2:禁用自动加载,手动触发HostingStartup执行
如果不想调整原有代码结构,可以关闭内置自动加载逻辑,在Startup.ConfigureServices末尾手动触发插件的启动逻辑:
- 首先在Program.cs中禁用自动加载HostingStartup:
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { // 清空自动加载的HostingStartup程序集列表,禁用自动加载 webBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, string.Empty); webBuilder.UseStartup<Startup>(); });
- 在Startup.ConfigureServices末尾手动按顺序执行插件逻辑:
using System.Reflection; using Microsoft.AspNetCore.Hosting; public void ConfigureServices(IServiceCollection services) { // 原有DI注册逻辑优先执行 services.AddControllers(); // ...其他原有注册代码 // 手动按顺序执行指定程序集的HostingStartup逻辑 var pluginAssemblies = new[] {"ClassLibrary1", "ClassLibrary2"}; var serviceProvider = services.BuildServiceProvider(); var hostEnv = serviceProvider.GetRequiredService<IWebHostEnvironment>(); foreach (var assemblyName in pluginAssemblies) { var assembly = Assembly.Load(assemblyName); var startupAttrs = assembly.GetCustomAttributes<HostingStartupAttribute>(); foreach (var attr in startupAttrs) { if (Activator.CreateInstance(attr.HostingStartupType) is IHostingStartup startup) { var tempBuilder = new WebHostBuilder(); tempBuilder.UseConfiguration(Configuration); tempBuilder.UseEnvironment(hostEnv.EnvironmentName); // 执行插件配置逻辑 startup.Configure(tempBuilder); // 应用插件注册的所有服务到当前容器 var tempBuilderServices = tempBuilder.Services; foreach (var descriptor in tempBuilderServices) { services.Add(descriptor); } } } } }
内容的提问来源于stack exchange,提问作者Prasad Kanaparthi
相关产品推荐
相关产品推荐

