配置文件中程序運行中,擔當着不可或缺的角色;一般狀況下,使用 visual studio 進行建立項目過程當中,項目配置文件會自動生成在項目根目錄下,如 appsettings.json,或者是被你們普遍使用的 appsettings.{env.EnvironmentName}.json;配置文件
做爲一個入口,可讓咱們在不更新代碼的狀況,對程序進行干預和調整,那麼對其加載過程的全面瞭解就顯得很是必要。json
在 Program.cs 文件中,查看如下代碼app
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>(); }
public static IWebHostBuilder CreateDefaultBuilder(string[] args) { var builder = new WebHostBuilder(); if (string.IsNullOrEmpty(builder.GetSetting(WebHostDefaults.ContentRootKey))) { builder.UseContentRoot(Directory.GetCurrentDirectory()); } if (args != null) { builder.UseConfiguration(new ConfigurationBuilder().AddCommandLine(args).Build()); } builder.UseKestrel((builderContext, options) => { options.Configure(builderContext.Configuration.GetSection("Kestrel")); }) .ConfigureAppConfiguration((hostingContext, config) => { var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); if (env.IsDevelopment()) { var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName)); if (appAssembly != null) { config.AddUserSecrets(appAssembly, optional: true); } } config.AddEnvironmentVariables(); if (args != null) { config.AddCommandLine(args); } }) .ConfigureLogging((hostingContext, logging) => { logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); logging.AddConsole(); logging.AddDebug(); logging.AddEventSourceLogger(); }) .ConfigureServices((hostingContext, services) => { // Fallback services.PostConfigure<HostFilteringOptions>(options => { if (options.AllowedHosts == null || options.AllowedHosts.Count == 0) { // "AllowedHosts": "localhost;127.0.0.1;[::1]" var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); // Fall back to "*" to disable. options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" }); } }); // Change notification services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>( new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration)); services.AddTransient<IStartupFilter, HostFilteringStartupFilter>(); }) .UseIIS() .UseIISIntegration() .UseDefaultServiceProvider((context, options) => { options.ValidateScopes = context.HostingEnvironment.IsDevelopment(); }); return builder; }
public static IWebHostBuilder CreateDefaultBuilder(string[] args) { var builder = new WebHostBuilder(); if (string.IsNullOrEmpty(builder.GetSetting(WebHostDefaults.ContentRootKey))) { builder.UseContentRoot(Directory.GetCurrentDirectory()); } if (args != null) { builder.UseConfiguration(new ConfigurationBuilder().AddCommandLine(args).Build()); } builder.UseKestrel((builderContext, options) => { options.Configure(builderContext.Configuration.GetSection("Kestrel")); }) .ConfigureAppConfiguration((hostingContext, config) => { var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); if (env.IsDevelopment()) { var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName)); if (appAssembly != null) { config.AddUserSecrets(appAssembly, optional: true); } } config.AddEnvironmentVariables(); if (args != null) { config.AddCommandLine(args); } }) .ConfigureLogging((hostingContext, logging) => { logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); logging.AddConsole(); logging.AddDebug(); logging.AddEventSourceLogger(); }) .ConfigureServices((hostingContext, services) => { // Fallback services.PostConfigure<HostFilteringOptions>(options => { if (options.AllowedHosts == null || options.AllowedHosts.Count == 0) { // "AllowedHosts": "localhost;127.0.0.1;[::1]" var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); // Fall back to "*" to disable. options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" }); } }); // Change notification services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>( new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration)); services.AddTransient<IStartupFilter, HostFilteringStartupFilter>(); }) .UseIIS() .UseIISIntegration() .UseDefaultServiceProvider((context, options) => { options.ValidateScopes = context.HostingEnvironment.IsDevelopment(); }); return builder; }
public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); }
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; }
var services = new ServiceCollection(); services.AddSingleton(_options); services.AddSingleton<IHostingEnvironment>(_hostingEnvironment); services.AddSingleton<Extensions.Hosting.IHostingEnvironment>(_hostingEnvironment); services.AddSingleton(_context); var builder = new ConfigurationBuilder() .SetBasePath(_hostingEnvironment.ContentRootPath) .AddConfiguration(_config); _configureAppConfigurationBuilder?.Invoke(_context, builder); var configuration = builder.Build(); services.AddSingleton<IConfiguration>(configuration); _context.Configuration = configuration;
以上這段代碼很是熟悉,由於在 Startup.cs 文件中,咱們也許會使用過 ServiceCollection 對象將業務系統的自定義對象加入服務上下文中,以方便後續接口注入使用。asp.net
一般狀況下,咱們都會使用默認的配置文件進行開發,或者使用 appsettings.{env.EnvironmentName}.json 的文件名稱方式來區分 開發/測試/產品 環境,根據環境變量加載不一樣的配置文件;但是這樣一來帶來了另一個管理上的問題,產品環境的配置參數和開發環境
是不一樣的,若是使用環境變量的方式控制配置文件的加載,則可能致使密碼泄露等風險;誠然,能夠手工在產品環境建立此文件,可是這樣一來,發佈流程將會變得很是繁瑣,稍有錯漏文件便會被覆蓋。ide
咱們推薦使用 AddJsonFile 加載產品環境配置,代碼以下學習
public Startup(IConfiguration configuration, IHostingEnvironment env) { Configuration = AddCustomizedJsonFile(env).Build(); } public ConfigurationBuilder AddCustomizedJsonFile(IHostingEnvironment env) { var build = new ConfigurationBuilder(); build.SetBasePath(env.ContentRootPath).AddJsonFile("appsettings.json", true, true); if (env.IsProduction()) { build.AddJsonFile(Path.Combine("/data/sites/config", "appsettings.json"), true, true); } return build; }
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, IFileProvider provider, string path, bool optional, bool reloadOnChange) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } if (string.IsNullOrEmpty(path)) { throw new ArgumentException(Resources.Error_InvalidFilePath, nameof(path)); } return builder.AddJsonFile(s => { s.FileProvider = provider; s.Path = path; s.Optional = optional; s.ReloadOnChange = reloadOnChange; s.ResolveFileProvider(); }); }
public IConfigurationRoot Build() { var providers = new List<IConfigurationProvider>(); foreach (var source in Sources) { var provider = source.Build(this); providers.Add(provider); } return new ConfigurationRoot(providers); }
public ConfigurationRoot(IList<IConfigurationProvider> providers) { if (providers == null) { throw new ArgumentNullException(nameof(providers)); } _providers = providers; foreach (var p in providers) { p.Load(); ChangeToken.OnChange(() => p.GetReloadToken(), () => RaiseChanged()); } }
private void RaiseChanged() { var previousToken = Interlocked.Exchange(ref _changeToken, new ConfigurationReloadToken()); previousToken.OnReload(); }
public override IConfigurationProvider Build(IConfigurationBuilder builder) { EnsureDefaults(builder); return new JsonConfigurationProvider(this); }
public FileConfigurationProvider(FileConfigurationSource source) { if (source == null) { throw new ArgumentNullException(nameof(source)); } Source = source; if (Source.ReloadOnChange && Source.FileProvider != null) { ChangeToken.OnChange( () => Source.FileProvider.Watch(Source.Path), () => { Thread.Sleep(Source.ReloadDelay); Load(reload: true); }); } }
值得注意的是,該監聽器不是在獲得文件變更通知後第一時間去從新加載配置文件,方法內部能夠看到,這裏有一個 Thread.Sleep(Source.ReloadDelay),而 ReloadDelay 的默認值爲:250ms,該屬性的描述爲測試
以上就是 asp.netcore 中配置文件加載的內部執行過程,從中咱們認識到,默認配置文件是如何加載,並將默認配置文件如何注入到系統中的,還學習到了若是在不一樣的環境下,選擇加載自定義配置文件的過程;但配置文件變更的時候,系統內部又是如何去把配置文件從新加載到內存中去的。ui