PlanTempusApp/Core/Configurations/ConfigurationBuilder.cs

153 lines
5.2 KiB
C#

using Newtonsoft.Json.Linq;
namespace Core.Configurations
{
public interface IConfigurationBuilder
{
ConfigurationBuilder AddProvider(IConfigurationProvider provider);
IConfigurationRoot Build();
List<IConfigurationProvider> ConfigurationProviders { get; }
}
public class ConfigurationBuilder : IConfigurationBuilder
{
public List<IConfigurationProvider> ConfigurationProviders { get; private set; } = [];
public ConfigurationBuilder AddProvider(IConfigurationProvider provider)
{
((IConfigurationBuilder)this).ConfigurationProviders.Add(provider);
return this;
}
public IConfigurationRoot Build()
{
foreach (var provider in ConfigurationProviders)
{
provider.Build();
}
//TODO: we need to come up with merge strategy, right now the latest key-path dominates
return new ConfigurationRoot(ConfigurationProviders);
}
}
public class Configuration : IConfiguration
{
List<IConfigurationProvider> _providers = [];
/// <summary>
/// Implements a string-based indexer for backwards compatibility with Microsoft.Extensions.Configuration.
/// This implementation is marked as obsolete and should be replaced with type-safe alternatives.
/// </summary>
/// <param name="key">The configuration key to retrieve.</param>
/// <returns>The configuration value for the specified key.</returns>
/// <exception cref="NotSupportedException">Thrown when attempting to set a value, as this operation is not supported.</exception>
[Obsolete("Use type-safe configuration methods instead")]
public string this[string key]
{
get => GetConfiguration(_providers, key);
set => throw new NotSupportedException();
}
List<IConfigurationProvider> IConfiguration.ConfigurationProviders
{
get { return _providers; }
set { _providers = value; }
}
internal static string GetConfiguration(IList<IConfigurationProvider> providers, string key)
{
string value = null;
foreach (var provider in providers)
{
var test = provider.Configuration().SelectToken(ConfigurationBinder.NormalizePath(key));
if (test != null)
value = test.ToString();
}
return value;
}
}
public class ConfigurationRoot : Configuration, IConfigurationRoot
{
public ConfigurationRoot(List<IConfigurationProvider> configurationProviders)
{
((IConfiguration)this).ConfigurationProviders = configurationProviders;
}
}
public static class ConfigurationBinder
{
public static string NormalizePath(string path)
{
return path?.Replace(":", ".", StringComparison.Ordinal) ?? string.Empty;
}
public static string GetConnectionString(this IConfigurationRoot configuration, string name)
{
return configuration.GetSection("ConnectionStrings").Get<string>(name);
}
public static IConfigurationSection GetSection(this IConfigurationRoot configuration, string path)
{
JToken value = null;
foreach (var provider in configuration.ConfigurationProviders)
{
var test = provider.Configuration().SelectToken(NormalizePath(path));
if (test != null)
value = test;
}
return new ConfigurationSection { Path = path, Key = path.Split(':').Last(), Value = value };
}
public static T Get<T>(this IConfigurationRoot configuration, string path)
{
JToken value = null;
foreach (var provider in configuration.ConfigurationProviders)
{
var test = provider.Configuration().SelectToken(NormalizePath(path));
if (test != null)
value = test;
}
return value.ToObject<T>();
}
public static T Get<T>(this IConfigurationSection configuration, string path)
{
var value = configuration.Value.SelectToken(NormalizePath(path)).ToObject<T>();
return value;
}
public static T ToObject<T>(this IConfigurationSection configuration)
{
var value = configuration.Value.ToObject<T>();
return value;
}
[Obsolete("Use ToObject")]
public static T Get<T>(this IConfigurationSection configuration)
{
return configuration.Value.ToObject<T>();
}
}
public interface IConfigurationProvider
{
void Build();
Newtonsoft.Json.Linq.JObject Configuration();
}
public class ConfigurationSection : IConfigurationSection
{
public required string Path { get; set; }
public required string Key { get; set; }
public required JToken Value { get; set; }
}
public interface IConfigurationSection
{
string Path { get; }
string Key { get; }
Newtonsoft.Json.Linq.JToken Value { get; set; }
}
}