| File: ConfigurationProvider.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> /// Defines the core behavior of configuration providers and provides a base for derived classes. /// </summary> public abstract class ConfigurationProvider : IConfigurationProvider { private ConfigurationReloadToken _reloadToken = new ConfigurationReloadToken(); /// <summary> /// Initializes a new <see cref="IConfigurationProvider"/>. /// </summary> protected ConfigurationProvider() { Data = new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase); } /// <summary> /// Gets or sets the configuration key-value pairs for this provider. /// </summary> protected IDictionary<string, string?> Data { get; set; } /// <summary> /// Attempts to find a value with the given key. /// </summary> /// <param name="key">The key to lookup.</param> /// <param name="value">When this method returns, contains the value if one is found.</param> /// <returns><see langword="true" /> if <paramref name="key" /> has a value; otherwise <see langword="false" />.</returns> public virtual bool TryGet(string key, out string? value) => Data.TryGetValue(key, out value); /// <summary> /// Sets a value for a given key. /// </summary> /// <param name="key">The configuration key to set.</param> /// <param name="value">The value to set.</param> public virtual void Set(string key, string? value) => Data[key] = value; /// <summary> /// Loads (or reloads) the data for this provider. /// </summary> public virtual void Load() { } /// <summary> /// Returns the list of keys that this provider has. /// </summary> /// <param name="earlierKeys">The earlier keys that other providers contain.</param> /// <param name="parentPath">The path for the parent IConfiguration.</param> /// <returns>The list of keys for this provider.</returns> public virtual IEnumerable<string> GetChildKeys( IEnumerable<string> earlierKeys, string? parentPath) { var results = new List<string>(); if (parentPath is null) { foreach (KeyValuePair<string, string?> kv in Data) { results.Add(Segment(kv.Key, 0)); } } else { Debug.Assert(ConfigurationPath.KeyDelimiter == ":"); foreach (KeyValuePair<string, string?> kv in Data) { if (kv.Key.Length > parentPath.Length && kv.Key.StartsWith(parentPath, StringComparison.OrdinalIgnoreCase) && kv.Key[parentPath.Length] == ':') { results.Add(Segment(kv.Key, parentPath.Length + 1)); } } } results.AddRange(earlierKeys); results.Sort(ConfigurationKeyComparer.Comparison); return results; } private static string Segment(string key, int prefixLength) { Debug.Assert(ConfigurationPath.KeyDelimiter == ":"); int indexOf = key.IndexOf(':', prefixLength); return indexOf < 0 ? key.Substring(prefixLength) : key.Substring(prefixLength, indexOf - prefixLength); } /// <summary> /// Returns a <see cref="IChangeToken"/> that can be used to listen when this provider is reloaded. /// </summary> /// <returns>The <see cref="IChangeToken"/>.</returns> public IChangeToken GetReloadToken() { return _reloadToken; } /// <summary> /// Triggers the reload change token and creates a new one. /// </summary> protected void OnReload() { ConfigurationReloadToken previousToken = Interlocked.Exchange(ref _reloadToken, new ConfigurationReloadToken()); previousToken.OnReload(); } /// <summary> /// Generates a string representing this provider name and relevant details. /// </summary> /// <returns>The configuration name.</returns> public override string ToString() => GetType().Name; } }