Auto stash before merge of "main" and "origin/main"

This commit is contained in:
Janus C. H. Knudsen 2025-02-02 23:13:17 +01:00
parent 21d7128e74
commit 521190475d
41 changed files with 991 additions and 1150 deletions

View file

@ -1,50 +0,0 @@

using Microsoft.Extensions.Configuration;
namespace Core.Configurations
{
public class AzureConfigurationManager
{
private static IConfigurationBuilder _configurationBuilder;
/// <summary>
/// This AppConfigBuilder assumes that AppConfigEndpoint and AppConfigLabelFilter are configured as Settings on Azure for the Application that needs them.
/// AppConfigEndpoint would look like this: Endpoint=https://config-dec-test.azconfig.io;Id=0-l9-s0:foo;Secret=somesecret/bar
/// </summary>
/// <param name="localSettingsFile">
/// Path relative to the base path stored in Microsoft.Extensions.Configuration.IConfigurationBuilder.Properties of builder.
/// </param>
public static IConfigurationBuilder AppConfigBuilder(string localSettingsFile)
{
if (_configurationBuilder == null)
{
var envConfiguration = new Microsoft.Extensions.Configuration.ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
System.Diagnostics.Trace.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(Console.Out));
var appConfigEndpoint = envConfiguration["AppConfigEndpoint"];
var appConfigLabel = envConfiguration["AppConfigLabelFilter"];
_configurationBuilder = new Microsoft.Extensions.Configuration.ConfigurationBuilder();
if (!string.IsNullOrEmpty(appConfigEndpoint))
{
_configurationBuilder
.AddAzureAppConfiguration(options =>
{
options.Connect(appConfigEndpoint);
options.Select(keyFilter: "*", labelFilter: appConfigLabel);
})
.AddEnvironmentVariables();
}
else
{
_configurationBuilder.SetBasePath(Directory.GetCurrentDirectory());
_configurationBuilder.AddJsonFile(localSettingsFile, optional: false);
}
}
return _configurationBuilder;
}
}
}

View file

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Core.Configurations.Common
{
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
public static class KeyValueToJson
{
public static JObject Convert(IEnumerable<KeyValuePair<string, JToken>> pairs)
{
var root = new JObject();
foreach (var pair in pairs)
{
var keys = pair.Key.Split(':');
var current = root;
// Gennemgå hierarkiet og opret underobjekter, hvis de ikke eksisterer
for (int i = 0; i < keys.Length - 1; i++)
{
var key = keys[i];
if (current[key] == null)
{
current[key] = new JObject();
}
current = (JObject)current[key];
}
// Håndter den sidste nøgle og tilføj værdien
var lastKey = keys[keys.Length - 1];
var value = ConvertValue(pair.Value);
// Hvis den sidste nøgle allerede eksisterer, tilføj til en liste
if (current[lastKey] != null)
{
// Hvis den allerede er en liste, tilføj til listen
if (current[lastKey].Type == JTokenType.Array)
{
((JArray)current[lastKey]).Add(value);
}
// Hvis den ikke er en liste, konverter til en liste
else
{
var existingValue = current[lastKey];
current[lastKey] = new JArray { existingValue, value };
}
}
// Ellers tilføj som en enkelt værdi
else
{
current[lastKey] = value;
}
}
return root;
}
private static JToken ConvertValue(object value)
{
// Hvis værdien allerede er en JToken, returner den direkte
if (value is JToken token)
{
return token;
}
// Konverter andre typer
return value switch
{
int i => new JValue(i),
double d => new JValue(d),
bool b => new JValue(b),
string s => new JValue(s),
_ => new JValue(value.ToString())
};
}
}
}

View file

@ -1,61 +1,116 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
namespace Core.Configurations
{
public class ConfigurationBuilder
{
private readonly List<IConfigurationProvider> _providers = new();
public interface IConfigurationBuilder
{
ConfigurationBuilder AddProvider(IConfigurationProvider provider);
IConfigurationRoot Build();
List<IConfigurationProvider> ConfigurationProviders { get; }
}
public ConfigurationBuilder AddProvider(IConfigurationProvider provider)
{
_providers.Add(provider);
return this;
}
public class ConfigurationBuilder : IConfigurationBuilder
{
public List<IConfigurationProvider> ConfigurationProviders { get; private set; } = [];
public IConfigurationRoot Build()
{
// Her kan du implementere din egen sammenlægningslogik
return new ConfigurationRoot(_providers);
}
}
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
public class ConfigurationRoot : IConfigurationRoot
{
public ConfigurationRoot(List<IConfigurationProvider> configurationProviders)
{
return new ConfigurationRoot(ConfigurationProviders);
}
}
}
public T GetSection<T>(string key)
{
throw new NotImplementedException();
}
}
public static class ConfigurationPredicateExtensions
{
public class ConfigurationRoot : IConfigurationRoot
{
List<IConfigurationProvider> IConfigurationRoot.ConfigurationProviders { get; set; }
public static IConfigurationSection GetSection(this IConfigurationRoot configurationSection, string key)
{
return null;
}
public ConfigurationRoot(List<IConfigurationProvider> configurationProviders)
{
((IConfigurationRoot)this).ConfigurationProviders = configurationProviders;
}
public static T Get<T>(this IConfigurationSection configuration, string key)
{
return default(T);
}
}
public interface IConfigurationProvider
{
Dictionary<string, object> Configuration();
}
}
public static class ConfigurationBinder
{
private 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));
public interface IConfigurationSection
{
string Key { get; }
string Path { get; }
string Value { get; set; }
}
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; }
}
}

View file

@ -1,14 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Core.Configurations
namespace Core.Configurations
{
public interface IConfigurationRoot
{
}
internal List<IConfigurationProvider> ConfigurationProviders { get; set; }
}
}

View file

@ -0,0 +1,54 @@
using Core.Exceptions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Core.Configurations.JsonConfigProvider
{
public static class JsonConfigExtension
{
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, string configurationFilePath = "appconfiguration.json", bool? optional = true, bool? reloadOnChange = false)
{
return builder.AddProvider(new JsonConfigProvider(builder, configurationFilePath, optional ?? true, reloadOnChange ?? false));
}
}
public interface IHasConfigurationFilePath
{
string ConfigurationFilePath { get; }
}
public class JsonConfigProvider : IConfigurationProvider, IHasConfigurationFilePath
{
private readonly IConfigurationBuilder _builder;
private readonly bool _reloadOnChange;
JObject _configuration;
public string ConfigurationFilePath { get; private set; }
public JsonConfigProvider() { }
public JsonConfigProvider(IConfigurationBuilder builder, string configurationFilePath, bool optional, bool reloadOnChange)
{
if (!optional && !File.Exists(configurationFilePath))
throw new ConfigurationException($"File not found, path: {configurationFilePath}");
if (optional && !File.Exists(configurationFilePath))
return;
ConfigurationFilePath = configurationFilePath;
_builder = builder;
_reloadOnChange = reloadOnChange;
}
public void Build()
{
using (StreamReader file = File.OpenText(ConfigurationFilePath))
using (JsonTextReader reader = new JsonTextReader(file))
{
_configuration = (JObject)JToken.ReadFrom(reader);
}
}
public JObject Configuration()
{
return _configuration;
}
}
}

View file

@ -1,115 +0,0 @@
using Microsoft.Extensions.Configuration;
using Npgsql;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Core.Configurations.PostgresqlConfigurationBuilder
{
public class PostgresConfigurationSource : Microsoft.Extensions.Configuration.IConfigurationSource
{
private readonly string _connectionString;
private readonly string _channel;
private readonly string _configurationQuery;
public PostgresConfigurationSource(string connectionString, string channel, string configurationQuery)
{
_connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
_channel = channel ?? throw new ArgumentNullException(nameof(channel));
_configurationQuery = configurationQuery ?? throw new ArgumentNullException(nameof(configurationQuery));
}
public Microsoft.Extensions.Configuration.IConfigurationProvider Build(IConfigurationBuilder builder)
{
return new PostgresConfigurationProvider(_connectionString, _channel, _configurationQuery);
}
}
public class PostgresConfigurationProvider : ConfigurationProvider, IDisposable
{
private readonly string _connectionString;
private readonly string _channel;
private readonly string _configurationQuery;
private readonly NpgsqlConnection _listenerConnection;
private bool _disposedValue;
public PostgresConfigurationProvider(string connectionString, string channel, string configurationQuery)
{
_connectionString = connectionString;
_channel = channel;
_configurationQuery = configurationQuery;
_listenerConnection = new NpgsqlConnection(connectionString);
// Start listening for notifications
StartListening();
}
private async void StartListening()
{
try
{
await _listenerConnection.OpenAsync();
_listenerConnection.Notification += OnNotificationReceived;
using var cmd = new NpgsqlCommand($"LISTEN {_channel};", _listenerConnection);
await cmd.ExecuteNonQueryAsync();
}
catch (Exception ex)
{
// Log error and possibly retry
Console.WriteLine($"Error starting listener: {ex.Message}");
}
}
private void OnNotificationReceived(object sender, NpgsqlNotificationEventArgs e)
{
if (e.Channel == _channel)
{
// Reload configuration and notify
Load();
OnReload();
}
}
public override void Load()
{
var data = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
using (var connection = new NpgsqlConnection(_connectionString))
{
connection.Open();
using var cmd = new NpgsqlCommand(_configurationQuery, connection);
using var reader = cmd.ExecuteReader();
while (reader.Read())
{
string key = reader.GetString(0);
string value = reader.GetString(1);
data[key] = value;
}
}
Data = data;
}
protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
_listenerConnection?.Dispose();
}
_disposedValue = true;
}
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}

View file

@ -1,31 +0,0 @@
using Microsoft.Extensions.Configuration;
namespace Core.Configurations.PostgresqlConfigurationBuilder
{
/// <summary>
/// LISTEN / NOTIFY in Postgresql
/// </summary>
public static class PostgresConfigurationExtensions
{
public static IConfigurationBuilder AddPostgresConfiguration(
this IConfigurationBuilder builder,
Action<PostgresConfigurationOptions> setupAction)
{
var options = new PostgresConfigurationOptions();
setupAction(options);
builder.Add(new PostgresConfigurationSource(
options.ConnectionString,
options.Channel,
options.ConfigurationQuery));
return builder;
}
}
public class PostgresConfigurationOptions
{
public string ConnectionString { get; set; }
public string Channel { get; set; }
public string ConfigurationQuery { get; set; }
}
}

View file

@ -0,0 +1,14 @@
namespace Core.Configurations.SmartConfigProvider;
public class AppConfiguration
{
public long Id { get; set; }
public string Key { get; set; }
public object Value { get; set; }
public string Label { get; set; }
public string ContentType { get; set; }
public DateTime? ValidFrom { get; set; }
public DateTime? ExpiresAt { get; set; }
public DateTime? CreatedAt { get; set; }
public DateTime? ModifiedAt { get; set; }
public Guid? Etag { get; set; }
}

View file

@ -0,0 +1,31 @@
using System.Data;
using Core.Configurations.SmartConfiguration;
using Insight.Database;
namespace Core.Configurations.SmartConfigProvider;
public class ConfigurationRepository : IConfigurationRepository
{
private readonly IDbConnection _connection;
public ConfigurationRepository(IDbConnection connection)
{
_connection = connection;
}
public ConfigurationRepository(string connectionString)
{
_connection = new Npgsql.NpgsqlConnection(connectionString);
}
public IEnumerable<AppConfiguration> GetActiveConfigurations()
{
const string sql = @"
SELECT id, ""key"", value, label, content_type,
valid_from, expires_at, created_at, modified_at, etag
FROM app_configuration
WHERE CURRENT_TIMESTAMP BETWEEN valid_from AND expires_at
OR (valid_from IS NULL AND expires_at IS NULL)";
return _connection.QuerySql<AppConfiguration>(sql);
}
}

View file

@ -0,0 +1,7 @@
using Core.Configurations.SmartConfigProvider;
namespace Core.Configurations.SmartConfiguration;
public interface IConfigurationRepository
{
IEnumerable<AppConfiguration> GetActiveConfigurations();
}

View file

@ -0,0 +1,74 @@
using Core.Configurations.JsonConfigProvider;
using Core.Configurations.SmartConfigProvider;
using Core.Exceptions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Core.Configurations.SmartConfig
{
public static class SmartConfigExtension
{
public static IConfigurationBuilder AddSmartConfig(this IConfigurationBuilder builder, string configKey = "DefaultConnection", string path = null)
{
return builder.AddProvider(new SmartConfigProvider(builder, configKey, path));
}
}
public class SmartConfigProvider : IConfigurationProvider
{
string _configKey;
string _connectionString;
string _path;
IConfigurationBuilder _builder;
Newtonsoft.Json.Linq.JObject _configuration;
public SmartConfigProvider() { }
public SmartConfigProvider(IConfigurationBuilder builder, string configKey, string configurationFilePath)
{
_builder = builder;
_configKey = configKey;
_path = configurationFilePath;
SetConnectionString();
}
void SetConnectionString()
{
var carrier = _builder.ConfigurationProviders.OfType<IHasConfigurationFilePath>().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<string, JToken>(x.Key, JToken.Parse(x.Value.ToString())));
_configuration = Common.KeyValueToJson.Convert(pairs);
}
public Newtonsoft.Json.Linq.JObject Configuration()
{
return _configuration;
}
}
}

View file

@ -1,14 +0,0 @@
namespace Core.Configurations.SmartConfiguration;
public class AppConfiguration
{
public long Id { get; set; }
public string Key { get; set; }
public string Value { get; set; }
public string Label { get; set; }
public string ContentType { get; set; }
public DateTime? ValidFrom { get; set; }
public DateTime? ExpiresAt { get; set; }
public DateTime? CreatedAt { get; set; }
public DateTime? ModifiedAt { get; set; }
public Guid? Etag { get; set; }
}

View file

@ -1,27 +0,0 @@
using Microsoft.Extensions.Configuration;
namespace Core.Configurations.SmartConfiguration
{
public static class ConfigurationExtensions
{
public static T Get<T>(this IConfigurationSection section) where T : class
{
if (section is JsonConfigurationSection jsonSection)
{
var token = jsonSection.GetToken();
return token?.ToObject<T>();
}
throw new InvalidOperationException("Section is not a JsonConfigurationSection");
}
public static T GetValue<T>(this IConfigurationSection section, string key)
{
if (section is JsonConfigurationSection jsonSection)
{
var token = jsonSection.GetToken().SelectToken(key.Replace(":", "."));
return token.ToObject<T>();
}
throw new InvalidOperationException("Section is not a JsonConfigurationSection");
}
}
}

View file

@ -1,24 +0,0 @@
using System.Data;
using Insight.Database;
namespace Core.Configurations.SmartConfiguration;
public class ConfigurationRepository : IConfigurationRepository
{
private readonly IDbConnection _connection;
public ConfigurationRepository(IDbConnection connection)
{
_connection = connection;
}
public async Task<IEnumerable<AppConfiguration>> GetActiveConfigurations()
{
const string sql = @"
SELECT id, key, value, label, content_type, valid_from, expires_at, created_at, modified_at, etag
FROM prod.app_configuration
WHERE (expires_at IS NULL OR expires_at > CURRENT_TIMESTAMP)
AND (valid_from IS NULL OR valid_from < CURRENT_TIMESTAMP)";
return await _connection.QueryAsync<AppConfiguration>(sql);
}
}

View file

@ -1,5 +0,0 @@
namespace Core.Configurations.SmartConfiguration;
public interface IConfigurationRepository
{
Task<IEnumerable<AppConfiguration>> GetActiveConfigurations();
}

View file

@ -1,34 +0,0 @@
using Newtonsoft.Json.Linq;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Primitives;
using System.Data;
namespace Core.Configurations.SmartConfiguration;
public class JsonConfiguration : Microsoft.Extensions.Configuration.IConfiguration
{
private readonly JObject _data;
public JsonConfiguration(JObject data)
{
_data = data;
}
public string this[string key]
{
get => _data.SelectToken(key.Replace(":", "."))?.ToString();
set => throw new NotImplementedException();
}
public Microsoft.Extensions.Configuration.IConfigurationSection GetSection(string key) => null;
//new JsonConfigurationSection(_data, key);
public IEnumerable<IConfigurationSection> GetChildren() =>
_data.Properties().Select(p => new JsonConfigurationSection(_data, p.Name));
public IChangeToken GetReloadToken() => throw new NotImplementedException();
IEnumerable<Microsoft.Extensions.Configuration.IConfigurationSection> IConfiguration.GetChildren()
{
throw new NotImplementedException();
}
}

View file

@ -1,80 +0,0 @@
using Newtonsoft.Json.Linq;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Primitives;
namespace Core.Configurations.SmartConfiguration
{
public class JsonConfigurationSection : IConfigurationSection
{
private readonly JObject _data;
private readonly string _path;
private readonly string _normalizedPath;
public JsonConfigurationSection(JObject data, string path)
{
_data = data ?? throw new ArgumentNullException(nameof(data));
_path = path ?? throw new ArgumentNullException(nameof(path));
_normalizedPath = NormalizePath(_path);
}
public string this[string key]
{
get
{
if (string.IsNullOrEmpty(key))
throw new ArgumentNullException(nameof(key));
var token = _data.SelectToken($"{_normalizedPath}.{NormalizePath(key)}");
return token?.ToString();
}
set => throw new NotImplementedException("Setting values is not supported.");
}
public string Key => _path.Split(':').Last();
public string Path => _path;
public string Value
{
get
{
var token = _data.SelectToken(_normalizedPath);
return token?.ToString();
}
set => throw new NotImplementedException("Setting values is not supported.");
}
public Microsoft.Extensions.Configuration.IConfigurationSection GetSection(string key)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentNullException(nameof(key));
return null;// new JsonConfigurationSection(_data, string.IsNullOrEmpty(_path) ? key : $"{_path}:{key}");
}
public JToken GetToken() => _data.SelectToken(_normalizedPath);
public IEnumerable<IConfigurationSection> GetChildren()
{
var token = _data.SelectToken(_normalizedPath);
if (token is JObject obj)
{
return obj.Properties()
.Select(p => new JsonConfigurationSection(_data, string.IsNullOrEmpty(_path) ? p.Name : $"{_path}:{p.Name}"));
}
return Enumerable.Empty<IConfigurationSection>();
}
public T Get<T>() where T : class
{
var token = _data.SelectToken(_normalizedPath);
return token?.ToObject<T>();
}
public IChangeToken GetReloadToken() => new ConfigurationReloadToken();
private static string NormalizePath(string path)
{
return path?.Replace(":", ".", StringComparison.Ordinal) ?? string.Empty;
}
}
}

View file

@ -1,83 +0,0 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Microsoft.Extensions.Configuration;
namespace Core.Configurations.SmartConfiguration
{
public class KeyValueConfigurationBuilder
{
private readonly IConfigurationRepository _repository;
private readonly JObject _rootObject = new();
private IConfiguration _configuration;
private readonly object _configurationLock = new();
public KeyValueConfigurationBuilder(IConfigurationRepository repository)
{
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
}
/// <summary>
/// Loads configurations from the repository and builds the configuration tree.
/// </summary>
public async Task LoadConfiguration()
{
try
{
var configurations = await _repository.GetActiveConfigurations();
foreach (var config in configurations)
AddKeyValue(config.Key, config.Value);
}
catch (Exception ex)
{
// Log the exception or handle it as needed
throw new InvalidOperationException("Failed to load configurations.", ex);
}
}
/// <summary>
/// Adds a key-value pair to the configuration tree.
/// </summary>
/// <param name="key">The key to add.</param>
/// <param name="jsonValue">The JSON value to add.</param>
public void AddKeyValue(string key, string jsonValue)
{
if (string.IsNullOrEmpty(key))
throw new ArgumentNullException(nameof(key));
if (string.IsNullOrEmpty(jsonValue))
throw new ArgumentNullException(nameof(jsonValue));
try
{
var valueObject = JsonConvert.DeserializeObject<JObject>(jsonValue);
var parts = key.Split(':');
JObject current = _rootObject;
for (int i = 0; i < parts.Length - 1; i++)
{
var part = parts[i];
if (!current.ContainsKey(part))
{
current[part] = new JObject();
}
current = (JObject)current[part];
}
current[parts[^1]] = valueObject;
}
catch (JsonException ex)
{
throw new ArgumentException("Invalid JSON value.", nameof(jsonValue), ex);
}
}
/// <summary>
/// Builds the configuration instance.
/// </summary>
/// <returns>The built <see cref="IConfiguration"/> instance.</returns>
public IConfiguration Build()
{
_configuration = new JsonConfiguration(_rootObject);
return _configuration;
}
}
}

View file

@ -1,48 +0,0 @@

using Microsoft.Extensions.Configuration;
namespace Core.Configurations
{
public class SmartConfigManager
{
private static IConfigurationBuilder _configurationBuilder;
/// <summary>
/// This AppConfigBuilder assumes that AppConfigEndpoint and AppConfigLabelFilter are configured as Settings on Azure for the Application that needs them.
/// AppConfigEndpoint would look like this: Endpoint=https://config-dec-test.azconfig.io;Id=0-l9-s0:foo;Secret=somesecret/bar
/// </summary>
/// <param name="localSettingsFile">
/// Path relative to the base path stored in Microsoft.Extensions.Configuration.IConfigurationBuilder.Properties of builder.
/// </param>
public static IConfigurationBuilder AddSmartConfigBuilder(string localSettingsFile)
{
if (_configurationBuilder == null)
{
var envConfiguration = new Microsoft.Extensions.Configuration.ConfigurationBuilder()
.AddEnvironmentVariables()
.Build();
var appConfigEndpoint = envConfiguration["AppConfigEndpoint"];
var appConfigLabel = envConfiguration["AppConfigLabelFilter"];
_configurationBuilder = new Microsoft.Extensions.Configuration.ConfigurationBuilder();
if (!string.IsNullOrEmpty(appConfigEndpoint))
{
_configurationBuilder
.AddAzureAppConfiguration(options =>
{
options.Connect(appConfigEndpoint);
options.Select(keyFilter: "*", labelFilter: appConfigLabel);
})
.AddEnvironmentVariables();
}
else
{
_configurationBuilder.SetBasePath(Directory.GetCurrentDirectory());
_configurationBuilder.AddJsonFile(localSettingsFile, optional: false);
}
}
return _configurationBuilder;
}
}
}

View file

@ -1,22 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Akka" Version="1.5.32" />
<PackageReference Include="Autofac" Version="8.1.1" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
<PackageReference Include="Insight.Database" Version="8.0.1" />
<PackageReference Include="Insight.Database.Providers.PostgreSQL" Version="8.0.1" />
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.22.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureAppConfiguration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0" />
<PackageReference Include="npgsql" Version="9.0.2" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Akka" Version="1.5.32" />
<PackageReference Include="Autofac" Version="8.1.1" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
<PackageReference Include="Insight.Database" Version="8.0.1" />
<PackageReference Include="Insight.Database.Providers.PostgreSQL" Version="8.0.1" />
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.22.0" />
<PackageReference Include="npgsql" Version="9.0.2" />
</ItemGroup>
<ItemGroup>
<Folder Include="Configurations\AzureAppConfigurationProvider\" />
<Folder Include="Configurations\PostgresqlConfigurationBuilder\" />
</ItemGroup>
</Project>