From d799eab511a93f145c81bc66a2b7a6edad0d450b Mon Sep 17 00:00:00 2001 From: TheXamlGuy Date: Wed, 24 Apr 2024 23:08:58 +0100 Subject: [PATCH] Added the abilty to load configuration sections using * pattern --- Toolkit.Avalonia/FrameHandler.cs | 4 +- Toolkit.Avalonia/NavigationPageFactory.cs | 10 +- Toolkit.Foundation/Create.cs | 9 +- Toolkit.Foundation/DefaultBuilder.cs | 148 +++++++++++++++++- .../IServiceCollectionExtensions.cs | 10 +- 5 files changed, 166 insertions(+), 15 deletions(-) diff --git a/Toolkit.Avalonia/FrameHandler.cs b/Toolkit.Avalonia/FrameHandler.cs index fa5a17d..ffe6781 100644 --- a/Toolkit.Avalonia/FrameHandler.cs +++ b/Toolkit.Avalonia/FrameHandler.cs @@ -32,8 +32,8 @@ public class FrameHandler(INavigationContext navigationContext) : if (control.DataContext is object content) { - if (content is IPrimaryConfirmation confirmNavigation && - !await confirmNavigation.Confirm()) + if (content is IConfirmation confirmation && + !await confirmation.Confirm()) { args.Cancel = true; } diff --git a/Toolkit.Avalonia/NavigationPageFactory.cs b/Toolkit.Avalonia/NavigationPageFactory.cs index 511d563..e7d1657 100644 --- a/Toolkit.Avalonia/NavigationPageFactory.cs +++ b/Toolkit.Avalonia/NavigationPageFactory.cs @@ -6,13 +6,7 @@ namespace Toolkit.Avalonia; public class NavigationPageFactory : INavigationPageFactory { - public Control? GetPage(Type srcType) - { - return default; - } + public Control? GetPage(Type srcType) => default; - public Control GetPageFromObject(object target) - { - return (Control)target; - } + public Control GetPageFromObject(object target) => (Control)target; } diff --git a/Toolkit.Foundation/Create.cs b/Toolkit.Foundation/Create.cs index 9483a29..45b2bb9 100644 --- a/Toolkit.Foundation/Create.cs +++ b/Toolkit.Foundation/Create.cs @@ -2,4 +2,11 @@ namespace Toolkit.Foundation; public record Create(TValue Value) : - INotification; \ No newline at end of file + INotification; + +public record Create +{ + public static Create As(TValue value) => new(value); + + public static Create As() where TValue : new() => new(new TValue()); +} \ No newline at end of file diff --git a/Toolkit.Foundation/DefaultBuilder.cs b/Toolkit.Foundation/DefaultBuilder.cs index 948e896..55eb938 100644 --- a/Toolkit.Foundation/DefaultBuilder.cs +++ b/Toolkit.Foundation/DefaultBuilder.cs @@ -1,9 +1,155 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.FileProviders.Physical; using Microsoft.Extensions.Hosting; +using System.Text.Json; namespace Toolkit.Foundation; +public static class Test +{ + public static IHostBuilder AddConfiguration(this IHostBuilder builder, + string section) + where TConfiguration : class, new() => + builder.AddConfiguration(section, "Settings.json", null); + + public static IHostBuilder AddConfiguration(this IHostBuilder services) + where TConfiguration : class, new() => + services.AddConfiguration(typeof(TConfiguration).Name, "Settings.json", null); + + public static IHostBuilder AddConfiguration(this IHostBuilder builder, + Action configurationDelegate) + where TConfiguration : class, new() + { + TConfiguration configuration = new(); + configurationDelegate.Invoke(configuration); + + return builder.AddConfiguration(typeof(TConfiguration).Name, "Settings.json", configuration); + } + + public static IHostBuilder AddConfiguration(this IHostBuilder builder, + Action configurationDelegate, + string section) + where TConfiguration : class, new() + { + TConfiguration configuration = new(); + configurationDelegate.Invoke(configuration); + + return builder.AddConfiguration(section, "Settings.json", configuration); + } + + public static IHostBuilder AddConfiguration(this IHostBuilder builder, + TConfiguration configuration) + where TConfiguration : class, new() => + builder.AddConfiguration(configuration.GetType().Name, "Settings.json", configuration); + + public static IHostBuilder AddConfiguration(this IHostBuilder builder, + object configuration) + where TConfiguration : class, new() => + builder.AddConfiguration(configuration.GetType().Name, + "Settings.json", (TConfiguration?)configuration); + + public static IHostBuilder AddConfiguration(this IHostBuilder builder, string section, + string path = "Settings.json", + TConfiguration? defaultConfiguration = null, + Action? serializerDelegate = null) + where TConfiguration : class, new() + { + builder.ConfigureServices((context, services) => + { + HashSet sections = []; + + if (section.EndsWith(":*")) + { + section = section[..^1]; + if (context.Configuration is ConfigurationRoot root) + { + foreach (KeyValuePair configuration in root.AsEnumerable()) + { + string[] segments = configuration.Key.Split(':'); + if (segments.Length > 2) + { + string keyPrefix = string.Join(':', segments.Take(2)); + if (!keyPrefix.EndsWith(":*")) + { + sections.Add(keyPrefix); + } + } + } + } + } + else + { + sections.Add(section); + } + + foreach (string section in sections) + { + services.TryAddSingleton>(provider => + { + IFileInfo? fileInfo = null; + if (provider.GetService() is IHostEnvironment hostEnvironment) + { + IFileProvider fileProvider = hostEnvironment.ContentRootFileProvider; + fileInfo = fileProvider.GetFileInfo(path); + } + + fileInfo ??= new PhysicalFileInfo(new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path))); + return new ConfigurationFile(fileInfo); + }); + + services.TryAddKeyedSingleton>(section, (provider, KeyAccelerator) => + { + JsonSerializerOptions? defaultSerializer = null; + if (serializerDelegate is not null) + { + defaultSerializer = new JsonSerializerOptions(); + serializerDelegate.Invoke(defaultSerializer); + } + + return new ConfigurationSource(provider.GetRequiredService>(), + section, defaultSerializer); + }); + + //services.AddHostedService>(); + services.TryAddKeyedTransient>(section, (provider, key) => + new ConfigurationReader(provider.GetRequiredKeyedService>(key), + provider.GetRequiredKeyedService>(key))); + + services.TryAddKeyedTransient>(section, (provider, key) => + new ConfigurationWriter(provider.GetRequiredKeyedService>(key))); + + services.TryAddKeyedTransient>(section, (provider, key) => + new ConfigurationFactory(() => defaultConfiguration ?? new TConfiguration())); + + services.AddTransient>(provider => + new ConfigurationInitializer(provider.GetRequiredKeyedService>(section), + provider.GetRequiredKeyedService>(section), + provider.GetRequiredKeyedService>(section), + provider.GetRequiredService())); + + services.AddTransient, ConfigurationInitializer>(provider => + provider.GetRequiredService().Create>(section)); + + services.AddTransient, WritableConfiguration>(); + + services.TryAddKeyedTransient>(section, (provider, key) => + new ConfigurationDescriptor(section, provider.GetRequiredKeyedService>(key))); + + services.AddTransient(provider => + provider.GetRequiredKeyedService>(section)); + + services.AddTransient(provider => + provider.GetRequiredKeyedService>(section).Value); + } + + }); + + return builder; + } +} public class DefaultBuilder : HostBuilder { @@ -11,7 +157,7 @@ public class DefaultBuilder : { return new HostBuilder() .UseContentRoot("Local", true) - .ConfigureAppConfiguration(config => + .ConfigureAppConfiguration((context, config) => { config.AddJsonFile("Settings.json", true, true); }) diff --git a/Toolkit.Foundation/IServiceCollectionExtensions.cs b/Toolkit.Foundation/IServiceCollectionExtensions.cs index e482ed6..e067f42 100644 --- a/Toolkit.Foundation/IServiceCollectionExtensions.cs +++ b/Toolkit.Foundation/IServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Configuration.Json; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders.Physical; @@ -146,8 +147,11 @@ public static class IServiceCollectionExtensions services.TryAddKeyedTransient>(section, (provider, key) => new ConfigurationDescriptor(section, provider.GetRequiredKeyedService>(key))); - services.AddTransient(provider => provider.GetRequiredKeyedService>(section)); - services.AddTransient(provider => provider.GetRequiredKeyedService>(section).Value); + services.AddTransient(provider => + provider.GetRequiredKeyedService>(section)); + + services.AddTransient(provider => + provider.GetRequiredKeyedService>(section).Value); return services; }