You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Web应用构建前从Azure App Configuration获取配置的正确方式

解决方案:绕开BuildServiceProvider,直接从配置系统绑定实例

你现在的问题核心是提前构建ServiceProvider导致单例服务重复实例化,但其实完全不需要走DI容器拿配置——所有配置源(包括Azure App Configuration)都已经加载到builder.Configuration里了,直接从配置节点绑定Settings实例即可,彻底避免BuildServiceProvider的副作用。

具体修改步骤

  1. 删除通过BuildServiceProvider获取IOptions<Settings>的代码块
  2. 直接从builder.Configuration中提取对应配置节点,绑定到Settings对象
  3. 若后续代码仍需通过DI获取IOptions<Settings>,可保留配置注册逻辑不影响现有使用

修改后的完整代码

var builder = WebApplication.CreateBuilder(args);

const string JSON = "json";
var appSettingsKey = CONSTANTS.APP.SETTINGS.APPSETTINGS.ToLower();

// 加载本地配置文件与环境变量
builder.Configuration.AddJsonFile($"{appSettingsKey}.{JSON}", optional: true, reloadOnChange: true);
builder.Configuration.AddJsonFile($"{appSettingsKey}.{builder.Environment.EnvironmentName}.{JSON}", optional: true, reloadOnChange: true);
builder.Configuration.AddEnvironmentVariables();

// 集成Azure App Configuration
builder.Configuration.AddAzureAppConfiguration(options => options.Connect(builder.Configuration.GetConnectionString(CONSTANTS.APP.SETTINGS.APP_CONFIGURATION_CONNECTION_STRING))
                        .Select(CONSTANTS.APP.SETTINGS.EQUINOX_SETTINGS_KEY_FILTER, CONSTANTS.APP.SETTINGS.EQUINOX_SETTINGS_LABEL_FILTER)
                        .ConfigureRefresh(refresh => refresh.Register($"{CONSTANTS.APP.SETTINGS.EQUINOX_SETTINGS_PREFIX}:{CONSTANTS.APP.SETTINGS.SENTINEL_KEY}", refreshAll: true))
                        .UseFeatureFlags());

// 直接从配置系统绑定Settings实例,无需构建ServiceProvider
var settingsSection = builder.Configuration.GetSection(CONSTANTS.APP.SETTINGS.EQUINOX_SETTINGS_PREFIX);
var settings = settingsSection.Get<Settings>() ?? throw new InvalidOperationException("无法加载Settings配置");

// 保留IOptions注册,供后续DI场景使用(可选)
builder.Services.Configure<Settings>(settingsSection);

// 正常使用Settings实例初始化Serilog、Orleans等服务
builder.Host.UseSerilog((hostBuilderContext, services, configuration) =>
{
    configuration.ConfigureLogging(CONSTANTS.CLUSTER.EQUINOX.ToUpper());
    configuration.AddApplicationInsightsLogging(services, hostBuilderContext.Configuration, settings);
});

builder.UseOrleans(settings);
builder.AddServices(settings);

var app = builder.Build();

为什么这种方式可行

  • 所有配置源(本地JSON、环境变量、Azure App Configuration)添加完成后,builder.Configuration已经完成了配置的加载、合并与解析,直接通过GetSection就能拿到完整的配置数据
  • 绑定Settings实例完全不依赖DI容器,从根源上避免了提前构建ServiceProvider导致的单例重复实例化问题
  • 若后续业务代码需要通过DI获取IOptions<Settings>,保留builder.Services.Configure<Settings>(settingsSection)即可,不影响原有逻辑

内容的提问来源于stack exchange,提问作者invernomuto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 15:02:35