More configuration work

This commit is contained in:
TheXamlGuy
2024-01-06 21:33:53 +00:00
parent 36c718c07e
commit 28af62d72d
14 changed files with 102 additions and 29 deletions
@@ -1,12 +1,13 @@
using Hyperbar.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Hyperbar.Widget.Contextual;
public class ContextualWidgetProvider :
IWidgetProvider
{
public void Create(IServiceCollection services) => services
.AddConfiguration<ContextualWidgetConfiguration>()
public void Create(HostBuilderContext comtext, IServiceCollection services) => services
.AddConfiguration<ContextualWidgetConfiguration>(comtext.Configuration.GetSection(nameof(ContextualWidgetConfiguration)))
.AddWidgetTemplate<ContextualWidgetViewModel>();
}
@@ -7,6 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Hyperbar\Hyperbar.csproj" />
@@ -1,6 +1,10 @@
namespace Hyperbar.Windows.Primary;
public class PrimaryWidgetConfiguration :
List<IPrimaryCommandConfiguration>
List<KeyAcceleratorCommandConfiguration>
{
public static PrimaryWidgetConfiguration Defaults => new()
{
new KeyAcceleratorCommandConfiguration { Icon = "Test", Key = "Test", Modifiers = ["Test", "Test"] }
};
}
@@ -1,13 +1,16 @@
using Hyperbar.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Hyperbar.Windows.Primary;
public class PrimaryWidgetProvider :
IWidgetProvider
{
public void Create(IServiceCollection services) => services.AddConfiguration<PrimaryWidgetConfiguration>()
.AddTransient<WidgetComponentMappinglFactory>()
.AddTransient(provider => provider.GetRequiredService<WidgetComponentMappinglFactory>().Create())
public void Create(HostBuilderContext comtext, IServiceCollection services) =>
services.AddConfiguration(comtext.Configuration.GetSection(nameof(PrimaryWidgetConfiguration)),
PrimaryWidgetConfiguration.Defaults)
.AddTransient<WidgetComponentMappingFactory>()
.AddTransient(provider => provider.GetRequiredService<WidgetComponentMappingFactory>().Create())
.AddWidgetTemplate<PrimaryWidgetViewModel>();
}
@@ -1,12 +1,12 @@
namespace Hyperbar.Windows.Primary;
public class WidgetComponentMappinglFactory :
MappingFactory<PrimaryWidgetConfiguration, IEnumerable<IWidgetComponentViewModel>>
public class WidgetComponentMappingFactory :
IMappingFactory<PrimaryWidgetConfiguration, IEnumerable<IWidgetComponentViewModel>>
{
private readonly PrimaryWidgetConfiguration configuration;
private readonly IServiceFactory service;
public WidgetComponentMappinglFactory(PrimaryWidgetConfiguration configuration,
public WidgetComponentMappingFactory(PrimaryWidgetConfiguration configuration,
IServiceFactory service)
{
this.configuration = configuration;
+2 -1
View File
@@ -5,6 +5,7 @@ using Hyperbar.Windows.Primary;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Microsoft.UI.Xaml;
namespace Hyperbar.Windows;
@@ -23,7 +24,7 @@ public partial class App :
.ConfigureAppConfiguration(config =>
{
config.SetBasePath(AppContext.BaseDirectory);
config.AddJsonFile("Settings.json", true);
config.AddJsonFile("Settings.json", true, true);
config.Build();
})
@@ -1,7 +1,10 @@
using Hyperbar.Extensions;
using Hyperbar.Windows.Interop;
using Hyperbar.Windows.Primary;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
namespace Hyperbar.Windows
{
@@ -13,8 +16,18 @@ namespace Hyperbar.Windows
{
TWidgetProvider builder = new();
IHost? host = new HostBuilder()
.ConfigureServices(isolatedServices =>
.UseContentRoot(AppContext.BaseDirectory)
.ConfigureAppConfiguration(config =>
{
config.SetBasePath(AppContext.BaseDirectory);
config.AddJsonFile("Settings.json", true, true);
config.Build();
})
.ConfigureServices((context, isolatedServices) =>
{
isolatedServices.AddHostedService<WidgetService>();
isolatedServices.AddSingleton<IServiceFactory>(provider =>
new ServiceFactory((type, parameters) => ActivatorUtilities.CreateInstance(provider, type, parameters!)));
@@ -29,10 +42,15 @@ namespace Hyperbar.Windows
isolatedServices.AddTransient<ITemplateFactory, TemplateFactory>();
isolatedServices.AddTransient<ITemplateGeneratorFactory, TemplateGeneratorFactory>();
builder.Create(isolatedServices);
builder.Create(context, isolatedServices);
}).Build();
services.AddTransient<IWidgetContext>(provider => new WidgetContext(host.Services));
host.Start();
var d = host.Services.GetService<IOptionsMonitor<PrimaryWidgetConfiguration>>();
return services;
}
}
@@ -0,0 +1,13 @@
namespace Hyperbar;
public class ConfigurationInitializer<TConfiguration>(DefaultConfiguration<TConfiguration> defaults,
IConfigurationWriter<TConfiguration> writer) : IInitializer
where TConfiguration :
class, new()
{
public Task InitializeAsync()
{
writer.Write(defaults.Configuration);
return Task.CompletedTask;
}
}
@@ -11,7 +11,7 @@ public class ConfigurationWriter<TConfiguration>(string path,
where TConfiguration :
class, new()
{
internal static Func<JsonSerializerOptions> DefaultSerializerOptions = new(() =>
private static readonly Func<JsonSerializerOptions> defaultSerializerOptions = new(() =>
{
return new JsonSerializerOptions
{
@@ -21,8 +21,6 @@ public class ConfigurationWriter<TConfiguration>(string path,
};
});
private readonly JsonSerializerOptions? serializerOptions = serializerOptions ??= DefaultSerializerOptions();
public void Write(Action<TConfiguration> updateDelegate)
{
if ((TryGet(out TConfiguration? value) ? value : new TConfiguration()) is TConfiguration updatedValue)
@@ -57,7 +55,7 @@ public class ConfigurationWriter<TConfiguration>(string path,
writer.WriteStartObject();
bool isWritten = false;
JsonDocument optionsElement = JsonDocument.Parse(JsonSerializer.SerializeToUtf8Bytes(value, serializerOptions));
JsonDocument optionsElement = JsonDocument.Parse(JsonSerializer.SerializeToUtf8Bytes(value, serializerOptions ?? defaultSerializerOptions()));
foreach (JsonProperty element in jsonDocument.RootElement.EnumerateObject())
{
@@ -91,7 +89,7 @@ public class ConfigurationWriter<TConfiguration>(string path,
using JsonDocument jsonDocument = JsonDocument.Parse(jsonContent);
if (jsonDocument.RootElement.TryGetProperty(section, out JsonElement sectionValue))
{
value = JsonSerializer.Deserialize<TConfiguration>(sectionValue.ToString(), serializerOptions);
value = JsonSerializer.Deserialize<TConfiguration>(sectionValue.ToString(), serializerOptions ?? defaultSerializerOptions());
return true;
}
}
@@ -0,0 +1,6 @@
namespace Hyperbar;
public class DefaultConfiguration<TConfiguration>(TConfiguration configuration)
{
public TConfiguration Configuration => configuration;
}
@@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting;
@@ -85,27 +86,30 @@ public static class IServiceCollectionExtensions
return serviceCollection;
}
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection services,
string path = "Settings.json")
IConfiguration configuration,
TConfiguration? defaults = null)
where TConfiguration :
class, new()
{
return services.AddConfiguration<TConfiguration>(typeof(TConfiguration).Name, path);
return services.AddConfiguration(configuration, typeof(TConfiguration).Name, "Settings.json", defaults);
}
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection services,
IConfiguration configuration,
string section,
string path = "Settings.json",
TConfiguration? defaults = null,
Action<JsonSerializerOptions>? serializerDelegate = null)
where TConfiguration :
class, new()
{
services.AddOptions();
services.Configure<TConfiguration>(configuration);
services.AddSingleton<IConfigureOptions<TConfiguration>>(new ConfigureNamedOptions<TConfiguration>("", args => { }));
services.AddTransient(provider => provider.GetService<IOptionsMonitor<TConfiguration>>()!.CurrentValue);
services.AddTransient<IConfigurationWriter<TConfiguration>>(provider =>
services.AddSingleton<IConfigurationWriter<TConfiguration>>(provider =>
{
string? jsonFilePath = null;
if (provider.GetService<IHostEnvironment>() is IHostEnvironment hostEnvironment)
@@ -118,16 +122,22 @@ public static class IServiceCollectionExtensions
jsonFilePath ??= Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path);
JsonSerializerOptions? defaultSerializerOptions = null;
JsonSerializerOptions? defaultSerializer = null;
if (serializerDelegate is not null)
{
defaultSerializerOptions = new JsonSerializerOptions();
serializerDelegate.Invoke(defaultSerializerOptions);
defaultSerializer = new JsonSerializerOptions();
serializerDelegate.Invoke(defaultSerializer);
}
return new ConfigurationWriter<TConfiguration>(jsonFilePath, section, defaultSerializerOptions);
return new ConfigurationWriter<TConfiguration>(jsonFilePath, section, defaultSerializer);
});
if (defaults is not null)
{
services.AddTransient(provider => new DefaultConfiguration<TConfiguration>(defaults));
services.AddTransient<IInitializer, ConfigurationInitializer<TConfiguration>>();
}
services.AddTransient<IWritableConfiguration<TConfiguration>, WritableConfiguration<TConfiguration>>();
return services;
}
@@ -1,6 +1,6 @@
namespace Hyperbar;
public interface MappingFactory<TFrom, TTo>
public interface IMappingFactory<TFrom, TTo>
{
TTo Create();
}
+2 -1
View File
@@ -1,8 +1,9 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Hyperbar;
public interface IWidgetProvider
{
void Create(IServiceCollection services);
void Create(HostBuilderContext context, IServiceCollection services);
}
+17
View File
@@ -0,0 +1,17 @@
using Microsoft.Extensions.Hosting;
namespace Hyperbar;
public class WidgetService(IEnumerable<IInitializer> initializers) :
IHostedService
{
public async Task StartAsync(CancellationToken cancellationToken)
{
foreach (IInitializer initializer in initializers)
{
await initializer.InitializeAsync();
}
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}