如何在Startup.ConfigureServices中使用IOptionsSnapshot实现Swagger配置热重载
解决方案
核心结论
没有可在Startup.ConfigureServices()中直接使用并实现IOptionsSnapshot重载的方案,原因如下:
ConfigureServices()仅在应用启动时执行一次,执行阶段服务容器尚未完成构建,无法解析出IOptionsSnapshot实例,且IOptionsSnapshot为接口,无法直接通过new关键字实例化IOptionsSnapshot是作用域服务,仅在每次请求触发时才会读取最新配置,即使你在启动阶段强行获取到配置值,也只会是启动时的静态值,后续配置变更无法同步更新
可行实现方案
你可以通过延迟绑定Swagger配置的方式实现无需重启服务重载Swagger配置,代码示例如下:
1. 调整ConfigureServices中的服务注册逻辑
using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; using Swashbuckle.AspNetCore.SwaggerUI; public void ConfigureServices(IServiceCollection services) { // 注册Swagger配置,只要配置源开启了重载(默认appsettings.json已开启reloadOnChange),就可以自动读取变更后的配置 services.Configure<SwaggerSettings>(Configuration.GetSection("BaseTemplate:Swagger")); // 注册Swagger核心服务 services.AddSwaggerGen(); // 动态配置Swagger生成规则 services.AddOptions<SwaggerGenOptions>() .Configure<IOptionsSnapshot<SwaggerSettings>>((swaggerGenOpts, swaggerSettingsSnap) => { var currentSettings = swaggerSettingsSnap.Value; // 在此处编写所有Swagger文档生成配置,每次请求都会读取最新的配置值 swaggerGenOpts.SwaggerDoc(currentSettings.Version, new OpenApiInfo { Title = currentSettings.Title, Version = currentSettings.Version, Description = currentSettings.Description }); // 其余Swagger配置(如安全方案、过滤器等)均可放在此处 }); // 如果需要Swagger UI也同步重载配置,添加以下配置 services.AddOptions<SwaggerUIOptions>() .Configure<IOptionsSnapshot<SwaggerSettings>>((swaggerUiOpts, swaggerSettingsSnap) => { var currentSettings = swaggerSettingsSnap.Value; swaggerUiOpts.SwaggerEndpoint($"/swagger/{currentSettings.Version}/swagger.json", $"{currentSettings.Title} {currentSettings.Version}"); // 其余UI配置均可放在此处 }); // 其余服务注册逻辑 }
2. 保持Configure方法中的中间件注册逻辑不变
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // 其余中间件... app.UseSwagger(); app.UseSwaggerUI(); // 其余中间件... }
实现原理
上述方案通过框架提供的Options延迟配置能力,将Swagger的配置逻辑延后到每次请求Swagger文档/UI时执行:每次请求会自动从当前请求作用域中获取最新的IOptionsSnapshot实例,读取变更后的配置生成Swagger内容,无需重启服务,修改配置后刷新Swagger页面即可生效。
注意事项
- 确保你的配置源开启了重载:默认.NET Core 3.0+模板中appsettings.json的
reloadOnChange参数默认为true,无需额外调整,如果使用自定义配置源需自行开启重载能力 - 不要在
ConfigureServices中直接同步读取配置值写死Swagger配置,否则只会读取启动时的静态值,无法实现重载
内容的提问来源于stack exchange,提问作者M. Ozn
相关产品推荐
相关产品推荐

