diff --git a/Toolkit.Foundation/Changed.cs b/Toolkit.Foundation/Changed.cs index e8a009b..1750921 100644 --- a/Toolkit.Foundation/Changed.cs +++ b/Toolkit.Foundation/Changed.cs @@ -7,4 +7,4 @@ public record Changed public static Changed As(TValue value) => new(value); public static Changed As() where TValue : new() => new(new TValue()); -} \ No newline at end of file +} diff --git a/Toolkit.Foundation/Component.cs b/Toolkit.Foundation/Component.cs new file mode 100644 index 0000000..2ea0c05 --- /dev/null +++ b/Toolkit.Foundation/Component.cs @@ -0,0 +1,30 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Toolkit.Foundation; + +public class Component : + IComponent +{ + private readonly IComponentBuilder builder; + + protected Component(IComponentBuilder builder) + { + this.builder = builder; + } + + public static TComponent? Create(IServiceProvider provider, + Action builderDelegate) + where TComponent : class, IComponent + { + if (provider.GetRequiredService() is IServiceFactory factory) + { + IComponentBuilder builder = ComponentBuilder.Create(); + builderDelegate(builder); + + return factory.Create(builder); + } + return default ; + } + + public virtual IComponentBuilder Create() => builder; +} \ No newline at end of file diff --git a/Toolkit.Foundation/ComponentFactory.cs b/Toolkit.Foundation/ComponentFactory.cs new file mode 100644 index 0000000..b23d95b --- /dev/null +++ b/Toolkit.Foundation/ComponentFactory.cs @@ -0,0 +1,57 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Toolkit.Foundation; + +public class ComponentFactory(IServiceProvider provider, + IProxyServiceCollection proxy, + IComponentScopeCollection scopes) : + IComponentFactory +{ + public IComponentHost? Create(string name, + ComponentConfiguration configuration, Action? servicesDelegate = null) + where TComponent : IComponent + { + if (provider.GetRequiredService() is TComponent component) + { + IComponentBuilder builder = component.Create(); + builder.AddServices(services => + { + services.AddTransient(_ => + provider.GetRequiredService>()); + + services.AddTransient(_ => + provider.GetRequiredService>()); + + services.AddScoped(_ => + provider.GetRequiredService()); + + services.AddScoped(_ => + provider.GetRequiredService()); + + services.AddScoped(_ => + provider.GetRequiredService()); + + services.AddTransient(_ => + provider.GetRequiredService()); + + services.AddRange(proxy.Services); + services.AddSingleton(new ComponentScope(name)); + + if (servicesDelegate is not null) + { + servicesDelegate(services); + } + }); + + builder.AddConfiguration(name, configuration); + IComponentHost host = builder.Build(); + + scopes.Add(new ComponentScopeDescriptor(name, + host.Services.GetRequiredService())); + + return host; + } + + return default; + } +} diff --git a/Toolkit.Foundation/DefaultHostBuilder.cs b/Toolkit.Foundation/DefaultHostBuilder.cs new file mode 100644 index 0000000..c238e97 --- /dev/null +++ b/Toolkit.Foundation/DefaultHostBuilder.cs @@ -0,0 +1,69 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Toolkit.Foundation; + +public class DefaultHostBuilder : + HostBuilder +{ + public static IHostBuilder Create() + { + return new HostBuilder() + .UseContentRoot("Local", true) + .ConfigureAppConfiguration((context, config) => + { + config.AddJsonFile("Settings.json", true, true); + }) + .ConfigureServices((context, services) => + { + services.AddScoped(provider => + new ServiceFactory((type, parameters) => ActivatorUtilities.CreateInstance(provider, type, parameters!))); + + services.AddSingleton(); + + services.AddScoped(); + services.AddScoped(); + services.AddTransient(); + services.AddTransient(); + + services.AddScoped(); + + services.AddScoped>(provider => + new ProxyService(provider.GetRequiredService())); + + services.AddScoped>(provider => + new ProxyService(provider.GetRequiredService())); + + services.AddScoped>(provider => + new ProxyService(provider.GetRequiredService())); + + services.AddScoped(); + + services.AddTransient(); + + services.AddTransient(); + + services.AddScoped(); + services.AddTransient(); + + services.AddTransient(); + + services.AddSingleton(new ComponentScope("Root")); + services.AddScoped(provider => new ComponentScopeCollection + { + new ComponentScopeDescriptor("Root", provider.GetRequiredService()) + }); + + services.AddTransient(); + services.AddTransient(); + + services.AddHandler(); + services.AddHandler(); + + services.AddInitializer(); + services.AddHostedService(); + }); + } +} \ No newline at end of file diff --git a/Toolkit.Foundation/IComponentFactory.cs b/Toolkit.Foundation/IComponentFactory.cs new file mode 100644 index 0000000..6380136 --- /dev/null +++ b/Toolkit.Foundation/IComponentFactory.cs @@ -0,0 +1,10 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Toolkit.Foundation; + +public interface IComponentFactory +{ + IComponentHost? Create(string name, + ComponentConfiguration configuration, Action? servicesDelegate = null) + where TComponent : IComponent; +} \ No newline at end of file diff --git a/Toolkit.Foundation/DefaultBuilder.cs b/Toolkit.Foundation/IHostBuilderExtension.cs similarity index 72% rename from Toolkit.Foundation/DefaultBuilder.cs rename to Toolkit.Foundation/IHostBuilderExtension.cs index 2d0309f..944977b 100644 --- a/Toolkit.Foundation/DefaultBuilder.cs +++ b/Toolkit.Foundation/IHostBuilderExtension.cs @@ -8,7 +8,7 @@ using System.Text.Json; namespace Toolkit.Foundation; -public static class Test +public static class IHostBuilderExtension { public static IHostBuilder AddConfiguration(this IHostBuilder builder, string section) @@ -149,66 +149,3 @@ public static class Test return builder; } } - -public class DefaultBuilder : - HostBuilder -{ - public static IHostBuilder Create() - { - return new HostBuilder() - .UseContentRoot("Local", true) - .ConfigureAppConfiguration((context, config) => - { - config.AddJsonFile("Settings.json", true, true); - }) - .ConfigureServices((context, services) => - { - services.AddScoped(provider => - new ServiceFactory((type, parameters) => ActivatorUtilities.CreateInstance(provider, type, parameters!))); - - services.AddSingleton(); - - services.AddScoped(); - services.AddScoped(); - services.AddTransient(); - services.AddTransient(); - - services.AddScoped(); - - services.AddScoped>(provider => - new ProxyService(provider.GetRequiredService())); - - services.AddScoped>(provider => - new ProxyService(provider.GetRequiredService())); - - services.AddScoped>(provider => - new ProxyService(provider.GetRequiredService())); - - services.AddScoped(); - - services.AddTransient(); - - services.AddTransient(); - - services.AddScoped(); - services.AddTransient(); - - services.AddTransient(); - - services.AddSingleton(new ComponentScope("Root")); - services.AddScoped(provider => new ComponentScopeCollection - { - new ComponentScopeDescriptor("Root", provider.GetRequiredService()) - }); - - services.AddTransient(); - - services.AddHandler(); - services.AddHandler(); - - services.AddInitializer(); - services.AddHostedService(); - }); - } -} \ No newline at end of file