introduce
This section brings you the newly added ConfigurationManager of. NET 6. Many people are curious about why to talk about this. You can read and load the configuration information easily. Let's look down.
This adds the new webapplication of ASP.NET Core and the types already used by WebApplicationBuilder, allowing reading from the configuration (such as appsettings.json and DOTNET_/ASPNETCORE_ environment variables), while still being able to add new configuration sources without explicitly rebuilding the configuration. Every time you add a source through the IConfiguration builder interface, IConfiguration is automatically updated immediately.
Review history
When developing with. NET 5, we use IConfigurationBuilder to add configuration source. Call the Build() builder to read each configuration source and build the final configuration IConfigurationRoot.
private static IConfigurationRoot BuildConfiguration() { var builder = new ConfigurationBuilder() .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../MyCompanyName.MyProjectName.DbMigrator/")) .AddJsonFile("appsettings.json", optional: false); return builder.Build(); }
Of course, our normal system development basically does not call ConfigurationBuilder or Build(), which is completed for us at the bottom of the. Net Core.
So what is the meaning of this type of launch?
Take chestnut use application ID and X.509 certificate for non azure hosted apps, which is an official case given by Microsoft. Let me explain that configuring the Azure Key Vault provider requires a configuration value, so do I have a chicken or an egg first - the configuration source cannot be added before building the configuration!.
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((context, config) => { if (context.HostingEnvironment.IsProduction()) { var builtConfig = config.Build(); using var store = new X509Store(StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly); var certs = store.Certificates.Find( X509FindType.FindByThumbprint, builtConfig["AzureADCertThumbprint"], false); config.AddAzureKeyVault(new Uri($"https://{builtConfig["KeyVaultName"]}.vault.azure.net/"), new ClientCertificateCredential(builtConfig["AzureADDirectoryId"], builtConfig["AzureADApplicationId"], certs.OfType<X509Certificate2>().Single()), new KeyVaultSecretManager()); store.Close(); } }) .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());
Our steps are:
- 1. Initialize configuration
- 2. Call IConfigurationBuilder.Build() to build the configuration
- 3. Retrieve the required configuration value from IConfigurationRoot
- 4. Add configuration source
- 5. The framework calls Build() to generate the final application configuration.
Here we call Build() twice. What's the problem?
Each call of ConfigurationBuilder.Build() will iterate over all sources, load providers, and generate a new instance ConfigurationRoot. Everyone should understand the consumption required to read the file.
New implementation
When we use the configuration manager, when IConfigurationSource adds an AddJsonFile() call, the provider will immediately load and update the configuration.
using var config = new ConfigurationManager(); config.AddEnvironmentVariables(prefix: "MyCustomPrefix_"); if (config["FileConfig"] == "enabled") { config.AddJsonFile("MyConfig.json", optional: true, reloadOnChange: true); } string myValueFromJson = config["JsonConfigValue"]; public class ConfigurationManager { private void AddSource(IConfigurationSource source) { lock (_providerLock) { IConfigurationProvider provider = source.Build(this); _providers.Add(provider); provider.Load(); _changeTokenRegistrations.Add(ChangeToken.OnChange(() => provider.GetReloadToken(), () => RaiseChanged())); } RaiseChanged(); } } private void ReloadSources() { lock (_providerLock) { DisposeRegistrationsAndProvidersUnsynchronized(); _changeTokenRegistrations.Clear(); _providers.Clear(); foreach (var source in _sources) { _providers.Add(source.Build(this)); } foreach (var p in _providers) { p.Load(); _changeTokenRegistrations.Add(ChangeToken.OnChange(() => p.GetReloadToken(), () => RaiseChanged())); } } RaiseChanged(); }
Note: the configuration manager must delete everything and start again after any source changes, traverse each source and reload them. If you do a lot of configuration source manipulation, using configuration manager will have the opposite effect
Configuration manager is suitable for configuring partial build and full build.
epilogue
Please don't care whether to use ConfigurationManager or ConfigurationBuilder when using. Net 6. It's best to use different loading schemes according to needs in development.
In addition, my distributed transaction implementation code is nearing the end, which will be explained later
Finally, you are welcome to pay attention to my blog, https://github.com/MrChuJiu/Dppt/tree/master/src Welcome, Star
Contact author: Jia Qun: 867095512 @ mrchujiu