多次调用IConfiguration.Build()是否可行?是否会引入Bug?
结论先行:多次调用ConfigurationBuilder.Build()本身是框架允许的操作,不会触发直接的运行时错误,但如果处理不当,很容易引入隐性Bug,结合你的示例场景,具体分析如下:
你的示例代码中存在的潜在风险
配置源不一致导致的读取差异
你手动构建的配置只加载了appsettings.json,但WebApplication.CreateBuilder默认会加载多套配置源:比如对应环境的appsettings.{Environment}.json、环境变量、命令行参数等。如果MyCommonService:Url这类配置存在于其他配置源中(比如生产环境的环境变量),手动构建的配置实例会读不到值,直接抛出ArgumentNullException,但框架自带的配置却能正常读取——这是典型的配置不一致Bug。配置热重载不同步
你手动开启了reloadOnChange: true,但这个配置实例是局部变量,后续配置文件修改后,只有这个实例会更新;而WebApplication.CreateBuilder创建的配置实例是独立的,两者不会同步。如果后续业务组件依赖框架配置,而日志组件依赖手动配置,就会出现配置更新后日志行为和业务预期不一致的情况。不必要的资源消耗
每次调用Build()都会创建一个新的IConfigurationRoot实例,每个实例都会单独监听配置文件的变化(如果开启了重载)。多次Build会生成多个监听器,虽然不会直接崩溃,但会增加不必要的文件监听资源占用。
边缘场景下的正确做法
如果因为第三方库限制(比如必须在DI容器构建前初始化)必须手动构建配置,建议:
- 对齐框架的配置源集合,确保手动配置和框架配置读取的是同一套数据。比如参考
WebApplication.CreateBuilder的默认配置逻辑来构建自己的配置:var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"; var c = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env}.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .AddCommandLine(args) .Build(); - 尽量复用配置实例,如果多次需要配置,不要重复Build,而是复用已构建好的
IConfigurationRoot实例,减少资源消耗。
针对你日志初始化场景的额外建议
你的场景是初始化NLog,其实NLog支持直接集成ASP.NET Core的配置系统,完全不需要手动构建配置。比如可以通过builder.Host.UseNLog()自动读取框架配置中的Logging节点,避免手动构建配置的麻烦。但如果因为第三方库限制必须提前初始化,那务必保证手动配置的源和框架一致,避免出现配置偏差。
内容的提问来源于stack exchange,提问作者Post Impatica

