| File: ConfigurationRoot.cs | Web Access |
| Project: src\runtime\src\libraries\Microsoft.Extensions.Configuration\src\Microsoft.Extensions.Configuration.csproj (Microsoft.Extensions.Configuration) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; using Microsoft.Extensions.Primitives; namespace Microsoft.Extensions.Configuration { /// <summary> /// Represents the root node for a configuration. /// </summary> [DebuggerDisplay("{DebuggerToString(),nq}")] [DebuggerTypeProxy(typeof(ConfigurationRootDebugView))] public class ConfigurationRoot : IConfigurationRoot, IDisposable { private readonly IList<IConfigurationProvider> _providers; private readonly List<IDisposable> _changeTokenRegistrations; private ConfigurationReloadToken _changeToken = new ConfigurationReloadToken(); /// <summary> /// Initializes a Configuration root with a list of providers. /// </summary> /// <param name="providers">The <see cref="IConfigurationProvider"/>s for this configuration.</param> public ConfigurationRoot(IList<IConfigurationProvider> providers) { ArgumentNullException.ThrowIfNull(providers); _providers = providers; _changeTokenRegistrations = new List<IDisposable>(providers.Count); foreach (IConfigurationProvider p in providers) { p.Load(); _changeTokenRegistrations.Add(ChangeToken.OnChange(p.GetReloadToken, RaiseChanged)); } } /// <summary> /// The <see cref="IConfigurationProvider"/>s for this configuration. /// </summary> public IEnumerable<IConfigurationProvider> Providers => _providers; /// <summary> /// Gets or sets the value corresponding to a configuration key. /// </summary> /// <param name="key">The configuration key.</param> /// <returns>The configuration value.</returns> public string? this[string key] { get => GetConfiguration(_providers, key); set => SetConfiguration(_providers, key, value); } /// <summary> /// Gets the immediate children subsections. /// </summary> /// <returns>The children.</returns> public IEnumerable<IConfigurationSection> GetChildren() => this.GetChildrenImplementation(null); /// <summary> /// Returns a <see cref="IChangeToken"/> that can be used to observe when this configuration is reloaded. /// </summary> /// <returns>The <see cref="IChangeToken"/>.</returns> public IChangeToken GetReloadToken() => _changeToken; /// <summary> /// Gets a configuration subsection with the specified key. /// </summary> /// <param name="key">The key of the configuration section.</param> /// <returns>The <see cref="IConfigurationSection"/>.</returns> /// <remarks> /// This method will never return <c>null</c>. If no matching subsection is found with the specified key, /// an empty <see cref="IConfigurationSection"/> is returned. /// </remarks> public IConfigurationSection GetSection(string key) => new ConfigurationSection(this, key); /// <summary> /// Forces the configuration values to be reloaded from the underlying sources. /// </summary> public void Reload() { foreach (IConfigurationProvider provider in _providers) { provider.Load(); } RaiseChanged(); } private void RaiseChanged() { ConfigurationReloadToken previousToken = Interlocked.Exchange(ref _changeToken, new ConfigurationReloadToken()); previousToken.OnReload(); } /// <inheritdoc /> public void Dispose() { // dispose change token registrations foreach (IDisposable registration in _changeTokenRegistrations) { registration.Dispose(); } // dispose providers foreach (IConfigurationProvider provider in _providers) { (provider as IDisposable)?.Dispose(); } } internal static string? GetConfiguration(IList<IConfigurationProvider> providers, string key) { for (int i = providers.Count - 1; i >= 0; i--) { IConfigurationProvider provider = providers[i]; if (provider.TryGet(key, out string? value)) { return value; } } return null; } internal static void SetConfiguration(IList<IConfigurationProvider> providers, string key, string? value) { if (providers.Count == 0) { throw new InvalidOperationException(SR.Error_NoSources); } foreach (IConfigurationProvider provider in providers) { provider.Set(key, value); } } private string DebuggerToString() { return $"Sections = {ConfigurationSectionDebugView.FromConfiguration(this, this).Count}"; } private sealed class ConfigurationRootDebugView { private readonly ConfigurationRoot _current; public ConfigurationRootDebugView(ConfigurationRoot current) { _current = current; } [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] public ConfigurationSectionDebugView[] Items => ConfigurationSectionDebugView.FromConfiguration(_current, _current).ToArray(); } } }