From f4f2fc47b18f24001ba8e28415ccdf2a64759948 Mon Sep 17 00:00:00 2001 From: "Janus C. H. Knudsen" Date: Tue, 11 Feb 2025 23:10:43 +0100 Subject: [PATCH] Adds option pattern for smart config --- .../IConfigurationRepository.cs | 1 + .../PostgresConfigurationRepository.cs} | 20 +++-- .../SmartConfigExtension.cs | 81 +------------------ .../SmartConfigProvider/SmartConfigOptions.cs | 28 +++++++ .../SmartConfigProvider.cs | 75 +++++++++++++++++ .../SmartConfigProviderTests.cs | 12 +++ 6 files changed, 130 insertions(+), 87 deletions(-) rename Core/Configurations/SmartConfigProvider/{ConfigurationRepository.cs => Repositories/PostgresConfigurationRepository.cs} (61%) create mode 100644 Core/Configurations/SmartConfigProvider/SmartConfigOptions.cs create mode 100644 Core/Configurations/SmartConfigProvider/SmartConfigProvider.cs diff --git a/Core/Configurations/SmartConfigProvider/IConfigurationRepository.cs b/Core/Configurations/SmartConfigProvider/IConfigurationRepository.cs index 079dd29..454ef09 100644 --- a/Core/Configurations/SmartConfigProvider/IConfigurationRepository.cs +++ b/Core/Configurations/SmartConfigProvider/IConfigurationRepository.cs @@ -3,6 +3,7 @@ using Core.Configurations.SmartConfigProvider; namespace Core.Configurations.SmartConfiguration; public interface IConfigurationRepository { + string ConnectionString { get; set; } IEnumerable GetActiveConfigurations(); } diff --git a/Core/Configurations/SmartConfigProvider/ConfigurationRepository.cs b/Core/Configurations/SmartConfigProvider/Repositories/PostgresConfigurationRepository.cs similarity index 61% rename from Core/Configurations/SmartConfigProvider/ConfigurationRepository.cs rename to Core/Configurations/SmartConfigProvider/Repositories/PostgresConfigurationRepository.cs index 8c8b417..83aeecf 100644 --- a/Core/Configurations/SmartConfigProvider/ConfigurationRepository.cs +++ b/Core/Configurations/SmartConfigProvider/Repositories/PostgresConfigurationRepository.cs @@ -2,21 +2,25 @@ using System.Data; using Core.Configurations.SmartConfiguration; using Insight.Database; -namespace Core.Configurations.SmartConfigProvider; -public class ConfigurationRepository : IConfigurationRepository +namespace Core.Configurations.SmartConfigProvider.Repositories; +public class PostgresConfigurationRepository : IConfigurationRepository { - private readonly IDbConnection _connection; + private IDbConnection _connection; + public string ConnectionString { get; set; } - public ConfigurationRepository(IDbConnection connection) - { - _connection = connection; - } - public ConfigurationRepository(string connectionString) + + public PostgresConfigurationRepository(string connectionString) { _connection = new Npgsql.NpgsqlConnection(connectionString); + } + public PostgresConfigurationRepository() + { + } public IEnumerable GetActiveConfigurations() { + _connection ??= new Npgsql.NpgsqlConnection(ConnectionString); + const string sql = @" SELECT id, ""key"", value, label, content_type, valid_from, expires_at, created_at, modified_at, etag diff --git a/Core/Configurations/SmartConfigProvider/SmartConfigExtension.cs b/Core/Configurations/SmartConfigProvider/SmartConfigExtension.cs index b63bfb0..dc5ebab 100644 --- a/Core/Configurations/SmartConfigProvider/SmartConfigExtension.cs +++ b/Core/Configurations/SmartConfigProvider/SmartConfigExtension.cs @@ -1,10 +1,4 @@ -using Core.Configurations.JsonConfigProvider; -using Core.Configurations.SmartConfigProvider; -using Core.Exceptions; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace Core.Configurations.SmartConfig +namespace Core.Configurations.SmartConfig { public static class SmartConfigExtension { @@ -24,78 +18,7 @@ namespace Core.Configurations.SmartConfig var options = new SmartConfigOptions(); setupAction(options); - return builder.AddProvider(new SmartConfigProvider(options.GetRepository())); - } - } - public class SmartConfigOptions - { - private SmartConfiguration.IConfigurationRepository _repository; - - public SmartConfigOptions UseRepository(SmartConfiguration.IConfigurationRepository repository) - { - _repository = repository; - return this; - } - - internal SmartConfiguration.IConfigurationRepository GetRepository() => _repository; - } - public class SmartConfigProvider : IConfigurationProvider - { - string _configKey; - string _connectionString; - string _path; - IConfigurationBuilder _builder; - - Newtonsoft.Json.Linq.JObject _configuration; - - - public SmartConfigProvider() { } - - public SmartConfigProvider(SmartConfiguration.IConfigurationRepository configurationProvider) - { } - public SmartConfigProvider(IConfigurationBuilder builder, string configKey, string configurationFilePath) - { - _builder = builder; - _configKey = configKey; - _path = configurationFilePath; - SetConnectionString(); - } - - void SetConnectionString() - { - var carrier = _builder.ConfigurationProviders.OfType().SingleOrDefault(); - - if (carrier?.ConfigurationFilePath is null && _path is null) - throw new ConfigurationException($"Expected a previous added ConfigurationProvider with IHasConfigurationFilePath or a configurationFilePath where to find the appsettingsfile"); - - _path ??= carrier.ConfigurationFilePath; - - if (!File.Exists(_path)) - throw new ConfigurationException($"File not found, configurationFilePath: {_path}"); - - - using (StreamReader file = File.OpenText(_path)) - using (JsonTextReader reader = new JsonTextReader(file)) - { - var jsonConfiguration = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.Linq.JToken.ReadFrom(reader); - - _connectionString = jsonConfiguration.SelectToken($"ConnectionStrings.{_configKey}")?.ToString(); - } - } - public void Build() - { - var repository = new ConfigurationRepository(_connectionString); - var configs = repository.GetActiveConfigurations(); - - var pairs = configs.Select(x => new KeyValuePair(x.Key, JToken.Parse(x.Value.ToString()))); - - _configuration = Common.KeyValueToJson.Convert(pairs); - - } - - public Newtonsoft.Json.Linq.JObject Configuration() - { - return _configuration; + return builder.AddProvider(new SmartConfigProvider(builder, options)); } } } diff --git a/Core/Configurations/SmartConfigProvider/SmartConfigOptions.cs b/Core/Configurations/SmartConfigProvider/SmartConfigOptions.cs new file mode 100644 index 0000000..1f9f60f --- /dev/null +++ b/Core/Configurations/SmartConfigProvider/SmartConfigOptions.cs @@ -0,0 +1,28 @@ +namespace Core.Configurations.SmartConfig +{ + public class SmartConfigOptions + { + private SmartConfiguration.IConfigurationRepository _repository; + internal string _configKey; + + public SmartConfigOptions UsePostgres(string configKey) + { + _configKey = configKey; + _repository = new Configurations.SmartConfigProvider.Repositories.PostgresConfigurationRepository(); + return this; + } + + public SmartConfigOptions UseSqlServer() + { + throw new NotImplementedException(); + } + + public SmartConfigOptions UseRepository(SmartConfiguration.IConfigurationRepository repository) + { + _repository = repository; + return this; + } + + internal SmartConfiguration.IConfigurationRepository GetRepository() => _repository; + } +} \ No newline at end of file diff --git a/Core/Configurations/SmartConfigProvider/SmartConfigProvider.cs b/Core/Configurations/SmartConfigProvider/SmartConfigProvider.cs new file mode 100644 index 0000000..72a1ad7 --- /dev/null +++ b/Core/Configurations/SmartConfigProvider/SmartConfigProvider.cs @@ -0,0 +1,75 @@ +using Core.Configurations.JsonConfigProvider; +using Core.Exceptions; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Core.Configurations.SmartConfig +{ + public class SmartConfigProvider : IConfigurationProvider + { + string _configKey; + string _connectionString; + string _path; + IConfigurationBuilder _builder; + + Newtonsoft.Json.Linq.JObject _configuration; + SmartConfigOptions _smartConfigOptions; + + public SmartConfigProvider() { } + + public SmartConfigProvider(IConfigurationBuilder builder, SmartConfigOptions smartConfigOptions) + { + _builder = builder; + _smartConfigOptions = smartConfigOptions; + _configKey = smartConfigOptions._configKey; + SetConnectionString(); + + } + public SmartConfigProvider(IConfigurationBuilder builder, string configKey, string configurationFilePath) + { + _builder = builder; + _configKey = configKey; + _path = configurationFilePath; + SetConnectionString(); + } + + void SetConnectionString() + { + var carrier = _builder.ConfigurationProviders.OfType().SingleOrDefault(); + + if (carrier?.ConfigurationFilePath is null && _path is null) + throw new ConfigurationException($"Expected a previous added ConfigurationProvider with IHasConfigurationFilePath or a configurationFilePath where to find the appsettingsfile"); + + _path ??= carrier.ConfigurationFilePath; + + if (!File.Exists(_path)) + throw new ConfigurationException($"File not found, configurationFilePath: {_path}"); + + + using (StreamReader file = File.OpenText(_path)) + using (JsonTextReader reader = new JsonTextReader(file)) + { + var jsonConfiguration = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.Linq.JToken.ReadFrom(reader); + + _connectionString = jsonConfiguration.SelectToken($"ConnectionStrings.{_configKey}")?.ToString(); + } + } + public void Build() + { + var repository = _smartConfigOptions.GetRepository(); + repository.ConnectionString = _connectionString; + + var configs = repository.GetActiveConfigurations(); + + var pairs = configs.Select(x => new KeyValuePair(x.Key, JToken.Parse(x.Value.ToString()))); + + _configuration = Common.KeyValueToJson.Convert(pairs); + + } + + public Newtonsoft.Json.Linq.JObject Configuration() + { + return _configuration; + } + } +} \ No newline at end of file diff --git a/Tests/ConfigurationTests/SmartConfigProviderTests.cs b/Tests/ConfigurationTests/SmartConfigProviderTests.cs index 1b49d74..a7c996a 100644 --- a/Tests/ConfigurationTests/SmartConfigProviderTests.cs +++ b/Tests/ConfigurationTests/SmartConfigProviderTests.cs @@ -7,6 +7,7 @@ using Autofac; using System.Data; using Insight.Database; using Npgsql; +using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Tests.ConfigurationTests { @@ -14,6 +15,17 @@ namespace Tests.ConfigurationTests public class SmartConfigProviderTests : TestFixture { + [TestMethod] + public void TrySmartConfigWithOptionsForPostgres() + { + var config = new ConfigurationBuilder() + .AddJsonFile("appconfiguration.dev.json") + .AddSmartConfig(options => options.UsePostgres("DefaultConnection")) + .Build(); + + var actualFeature = config.Get("Database:UseSSL"); + + } [TestMethod] public void Get_ShouldReturnCorrectValueAsBool() {