using Newtonsoft.Json.Linq; namespace Core.Configurations { public interface IConfigurationBuilder { ConfigurationBuilder AddProvider(IConfigurationProvider provider); IConfigurationRoot Build(); List ConfigurationProviders { get; } } public class ConfigurationBuilder : IConfigurationBuilder { public List 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 return new ConfigurationRoot(ConfigurationProviders); } } public class Configuration : IConfiguration { List _providers = []; public string this[string key] { get => GetConfiguration(_providers, key); set => throw new NotSupportedException(); } List IConfiguration.ConfigurationProviders { get { return _providers; } set { _providers = value; } } internal static string GetConfiguration(IList 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 { List IConfiguration.ConfigurationProviders { get; set; } public ConfigurationRoot(List 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(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(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(); } public static T Get(this IConfigurationSection configuration, string path) { var value = configuration.Value.SelectToken(NormalizePath(path)).ToObject(); return value; } public static T ToObject(this IConfigurationSection configuration) { var value = configuration.Value.ToObject(); return value; } [Obsolete("Use ToObject")] public static T Get(this IConfigurationSection configuration) { return configuration.Value.ToObject(); } } 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; } } }