diff --git a/Controls/Avalonia/Avalonia.csproj b/Controls/Avalonia/Avalonia.csproj deleted file mode 100644 index 312672e..0000000 --- a/Controls/Avalonia/Avalonia.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - net7.0 - enable - enable - Toolkit.Controls.Avalonia - Toolkit.Controls.Avalonia - - - - - \ No newline at end of file diff --git a/Controls/Avalonia/ContentDialog/ContentDialog.cs b/Controls/Avalonia/ContentDialog/ContentDialog.cs deleted file mode 100644 index 3d2f7c6..0000000 --- a/Controls/Avalonia/ContentDialog/ContentDialog.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Avalonia.Styling; - -namespace Toolkit.Controls.Avalonia; - -public class ContentDialog : FluentAvalonia.UI.Controls.ContentDialog, IStyleable -{ - Type IStyleable.StyleKey => typeof(FluentAvalonia.UI.Controls.ContentDialog); -} \ No newline at end of file diff --git a/Controls/Avalonia/Frame/Frame.cs b/Controls/Avalonia/Frame/Frame.cs deleted file mode 100644 index 338ac19..0000000 --- a/Controls/Avalonia/Frame/Frame.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Avalonia.Styling; - -namespace Toolkit.Controls.Avalonia; - -public class Frame : FluentAvalonia.UI.Controls.Frame, IStyleable -{ - Type IStyleable.StyleKey => typeof(FluentAvalonia.UI.Controls.Frame); -} \ No newline at end of file diff --git a/Controls/Avalonia/IconElement/ContentIcon.cs b/Controls/Avalonia/IconElement/ContentIcon.cs deleted file mode 100644 index bb608d3..0000000 --- a/Controls/Avalonia/IconElement/ContentIcon.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Controls.Templates; -using Avalonia.LogicalTree; -using Avalonia.Metadata; - -namespace Toolkit.Controls.Avalonia; - -public class ContentIcon : FluentAvalonia.UI.Controls.FAIconElement -{ - public static readonly StyledProperty IconTemplateProperty = - AvaloniaProperty.Register("IconTemplate"); - - public static readonly StyledProperty ContentProperty = - AvaloniaProperty.Register("Content"); - - [Content] - public object Content - { - get => GetValue(ContentProperty); - set => SetValue(ContentProperty, value); - } - - private ContentControl? content; - - protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e) - { - if (VisualChildren.Count > 0) - { - ((ILogical)VisualChildren[0]).NotifyAttachedToLogicalTree(e); - } - - base.OnAttachedToLogicalTree(e); - } - - /// - protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e) - { - if (VisualChildren.Count > 0) - { - ((ILogical)VisualChildren[0]).NotifyDetachedFromLogicalTree(e); - } - - base.OnDetachedFromLogicalTree(e); - } - - - public IDataTemplate IconTemplate - { - get => GetValue(IconTemplateProperty); - set => SetValue(IconTemplateProperty, value); - } - - protected override Size MeasureOverride(Size availableSize) - { - if (content == null) - { - CreateContent(); - } - - return base.MeasureOverride(availableSize); - - } - - private void CreateContent() - { - content = new ContentControl(); - - content.Bind(ContentControl.ContentProperty, this.GetBindingObservable(ContentProperty)); - content.Bind(ContentControl.ContentTemplateProperty, this.GetBindingObservable(IconTemplateProperty)); - - LogicalChildren.Add(content); - VisualChildren.Add(content); - } -} \ No newline at end of file diff --git a/Controls/Avalonia/IconElement/FAIconElement.cs b/Controls/Avalonia/IconElement/FAIconElement.cs deleted file mode 100644 index 5347c44..0000000 --- a/Controls/Avalonia/IconElement/FAIconElement.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Toolkit.Controls.Avalonia; - -public class FAIconElement : FluentAvalonia.UI.Controls.FAIconElement -{ - -} diff --git a/Controls/Avalonia/IconElement/FAPathIcon.cs b/Controls/Avalonia/IconElement/FAPathIcon.cs deleted file mode 100644 index de87c81..0000000 --- a/Controls/Avalonia/IconElement/FAPathIcon.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Toolkit.Controls.Avalonia; - -public class FAPathIcon : FluentAvalonia.UI.Controls.FAPathIcon -{ - -} diff --git a/Controls/Avalonia/IconElement/FontIcon.cs b/Controls/Avalonia/IconElement/FontIcon.cs deleted file mode 100644 index b4b19a6..0000000 --- a/Controls/Avalonia/IconElement/FontIcon.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Toolkit.Controls.Avalonia; - -public class FontIcon : FluentAvalonia.UI.Controls.FontIcon -{ - -} \ No newline at end of file diff --git a/Controls/Avalonia/IconElement/SymbolIcon.cs b/Controls/Avalonia/IconElement/SymbolIcon.cs deleted file mode 100644 index 1a4fe93..0000000 --- a/Controls/Avalonia/IconElement/SymbolIcon.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Toolkit.Controls.Avalonia; - -public class SymbolIcon : FluentAvalonia.UI.Controls.SymbolIcon -{ - -} diff --git a/Controls/Avalonia/NavigationView/NavigationView.cs b/Controls/Avalonia/NavigationView/NavigationView.cs deleted file mode 100644 index ac0ef05..0000000 --- a/Controls/Avalonia/NavigationView/NavigationView.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Avalonia.Styling; - -namespace Toolkit.Controls.Avalonia; - -public class NavigationView : FluentAvalonia.UI.Controls.NavigationView, IStyleable -{ - Type IStyleable.StyleKey => typeof(FluentAvalonia.UI.Controls.NavigationView); -} \ No newline at end of file diff --git a/Controls/Avalonia/NavigationView/NavigationViewItem.cs b/Controls/Avalonia/NavigationView/NavigationViewItem.cs deleted file mode 100644 index 357fabf..0000000 --- a/Controls/Avalonia/NavigationView/NavigationViewItem.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Avalonia.Controls.Primitives; -using Avalonia.Styling; -using Avalonia.VisualTree; -using FluentAvalonia.UI.Controls; - -namespace Toolkit.Controls.Avalonia; - -public class NavigationViewItem : FluentAvalonia.UI.Controls.NavigationViewItem, IStyleable -{ - private NavigationView? navigationView; - - public event EventHandler? Invoked; - - Type IStyleable.StyleKey => typeof(FluentAvalonia.UI.Controls.NavigationViewItem); - - protected override void OnApplyTemplate(TemplateAppliedEventArgs args) - { - navigationView = this.FindAncestorOfType(); - if (navigationView is not null) - { - navigationView.ItemInvoked += OnItemInvoked; - } - - base.OnApplyTemplate(args); - } - - private void OnItemInvoked(object? sender, NavigationViewItemInvokedEventArgs args) - { - if (args.InvokedItemContainer == this) - { - Invoked?.Invoke(this, args); - } - } -} diff --git a/Controls/Avalonia/Properties/Assembly.cs b/Controls/Avalonia/Properties/Assembly.cs deleted file mode 100644 index cb305e9..0000000 --- a/Controls/Avalonia/Properties/Assembly.cs +++ /dev/null @@ -1,3 +0,0 @@ -using Avalonia.Metadata; - -[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Toolkit.Controls.Avalonia")] \ No newline at end of file diff --git a/Controls/Avalonia/SettingsExpander/SettingsExpander.cs b/Controls/Avalonia/SettingsExpander/SettingsExpander.cs deleted file mode 100644 index 6825d54..0000000 --- a/Controls/Avalonia/SettingsExpander/SettingsExpander.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Avalonia.Styling; - -namespace Toolkit.Controls.Avalonia; - -public class SettingsExpander : FluentAvalonia.UI.Controls.SettingsExpander, IStyleable -{ - Type IStyleable.StyleKey => typeof(FluentAvalonia.UI.Controls.SettingsExpander); -} \ No newline at end of file diff --git a/Controls/Avalonia/Themes/ControlResources.axaml b/Controls/Avalonia/Themes/ControlResources.axaml deleted file mode 100644 index f7b96f4..0000000 --- a/Controls/Avalonia/Themes/ControlResources.axaml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/Framework/Avalonia/Avalonia.csproj b/Framework/Avalonia/Avalonia.csproj deleted file mode 100644 index e79bdca..0000000 --- a/Framework/Avalonia/Avalonia.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - net7.0 - enable - enable - Toolkit.Framework.Avalonia - Toolkit.Framework.Avalonia - - - - - - - - - - \ No newline at end of file diff --git a/Framework/Avalonia/Contents/ContentHandler.cs b/Framework/Avalonia/Contents/ContentHandler.cs deleted file mode 100644 index d951361..0000000 --- a/Framework/Avalonia/Contents/ContentHandler.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Avalonia; -using Toolkit.Framework.Foundation; - -namespace Toolkit.Framework.Avalonia; - -public class ContentHandler : IRequestHandler -{ - private readonly INamedContentTemplateFactory namedContentTemplateFactory; - private readonly INamedContentFactory namedContentFactory; - private readonly IContentTemplateFactory contentTemplateFactory; - private readonly ITypedContentFactory typedContentFactory; - - public ContentHandler(IContentTemplateFactory contentTemplateFactory, - INamedContentFactory namedContentFactory, - INamedContentTemplateFactory namedContentTemplateFactory, - ITypedContentFactory typedContentFactory) - { - this.contentTemplateFactory = contentTemplateFactory; - this.namedContentFactory = namedContentFactory; - this.namedContentTemplateFactory = namedContentTemplateFactory; - this.typedContentFactory = typedContentFactory; - } - - public ValueTask Handle(Content request, CancellationToken cancellationToken) - { - object? content = null; - object? template = null; - - if (request.Name is { Length: > 0 } name) - { - content = namedContentFactory.Create(name, request.Parameters); - template = namedContentTemplateFactory.Create(name); - } - - if (request.Type is Type type) - { - content = typedContentFactory.Create(type, request.Parameters); - template = contentTemplateFactory.Create(content); - } - - if (template is Visual visual) - { - visual.DataContext = content; - return new ValueTask(visual); - } - - return default; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Contents/ContentTemplateSelector.cs b/Framework/Avalonia/Contents/ContentTemplateSelector.cs deleted file mode 100644 index 5aaa825..0000000 --- a/Framework/Avalonia/Contents/ContentTemplateSelector.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Avalonia.Controls; -using Avalonia.Controls.Templates; -using Toolkit.Framework.Foundation; - -namespace Toolkit.Framework.Avalonia; - -public class ContentTemplateSelector : IDataTemplate, IContentTemplateSelector -{ - private readonly Dictionary dataTracking = new(); - - private readonly IContentTemplateFactory templateFactory; - - public ContentTemplateSelector(IContentTemplateFactory templateFactory) - { - this.templateFactory = templateFactory; - } - - public IControl? Build(object? content) - { - if (content is not null) - { - if (dataTracking.TryGetValue(content, out IControl? control)) - { - return control; - } - else - { - control = (IControl?)templateFactory.Create(content); - } - - return control; - } - - return null; - } - - public bool Match(object? data) - { - return true; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Extensions/EventArgsExtensions.cs b/Framework/Avalonia/Extensions/EventArgsExtensions.cs deleted file mode 100644 index 18ee73b..0000000 --- a/Framework/Avalonia/Extensions/EventArgsExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Avalonia.Data.Converters; -using System.Globalization; - -namespace Toolkit.Framework.Avalonia; - -public static class EventArgsExtensions -{ - public static dynamic? GetEventArguments(this EventArgs args, string? path, IValueConverter? converter, object? converterParameter) - { - return !string.IsNullOrWhiteSpace(path) ? GetEventArgsPropertyPathValue(args, path) : converter is not null ? converter.Convert(args, typeof(object), converterParameter, CultureInfo.CurrentCulture) : (dynamic)args; - } - - private static object GetEventArgsPropertyPathValue(object args, string path) - { - object? value = args; - if (path is { }) - { - value = PropertyPathHelper.GetValue(args, path); - } - - return value; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Extensions/IHostBuilderExtensions.cs b/Framework/Avalonia/Extensions/IHostBuilderExtensions.cs deleted file mode 100644 index 300219e..0000000 --- a/Framework/Avalonia/Extensions/IHostBuilderExtensions.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Hosting; -using Toolkit.Framework.Foundation; - -namespace Toolkit.Framework.Avalonia; - -public static class IHostBuilderExtensions -{ - public static IHostBuilder ConfigureContents(this IHostBuilder hostBuilder, Action builderDelegate) - { - hostBuilder.ConfigureServices((hostBuilderContext, serviceCollection) => - { - ContentTemplateBuilder? builder = new(); - builderDelegate?.Invoke(builder); - - serviceCollection.TryAddSingleton(builder.Descriptors); - serviceCollection.TryAddSingleton(); - serviceCollection.TryAddSingleton(); - serviceCollection.TryAddSingleton(); - serviceCollection.TryAddSingleton(); - serviceCollection.TryAddSingleton(); - serviceCollection.TryAddSingleton(); - - foreach (IContentTemplateDescriptor? descriptor in builder.Descriptors) - { - serviceCollection.Add(new ServiceDescriptor(descriptor.TemplateType, descriptor.TemplateType, descriptor.Lifetime)); - serviceCollection.Add(new ServiceDescriptor(descriptor.ContentType, descriptor.ContentType, descriptor.Lifetime)); - } - }); - - return hostBuilder; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Extensions/IServiceCollectionExtensions.cs b/Framework/Avalonia/Extensions/IServiceCollectionExtensions.cs deleted file mode 100644 index 54ef11d..0000000 --- a/Framework/Avalonia/Extensions/IServiceCollectionExtensions.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Toolkit.Framework.Foundation; - -namespace Toolkit.Framework.Avalonia; - -public static class IServiceCollectionExtensions -{ - public static IServiceCollection AddAvalonia(this IServiceCollection serviceCollection) - { - serviceCollection.TryAddSingleton(); - - serviceCollection.AddHandler(); - serviceCollection.AddHandler(); - serviceCollection.AddHandler(); - serviceCollection.AddHandler(); - serviceCollection.AddHandler(); - serviceCollection.AddHandler(); - - return serviceCollection; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Extensions/MarkupExtensions.cs b/Framework/Avalonia/Extensions/MarkupExtensions.cs deleted file mode 100644 index 83bac02..0000000 --- a/Framework/Avalonia/Extensions/MarkupExtensions.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Avalonia.Data; - -namespace Toolkit.Framework.Avalonia; - -public static class MarkupExtensions -{ - public static Binding? ToBinding(this object value) - { - if (value is Binding) - { - return value as Binding; - } - - return new Binding { Mode = BindingMode.OneWay, Source = value }; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Extensions/PropertyPathHelper..cs b/Framework/Avalonia/Extensions/PropertyPathHelper..cs deleted file mode 100644 index 929873a..0000000 --- a/Framework/Avalonia/Extensions/PropertyPathHelper..cs +++ /dev/null @@ -1,27 +0,0 @@ -using Avalonia; -using Avalonia.Data; - -namespace Toolkit.Framework.Avalonia; - -public static class PropertyPathHelper -{ - private static readonly Dummy dummy = new(); - - public static object GetValue(object args, string path) - { - Binding binding = new(path) - { - Mode = BindingMode.OneTime, - Source = args - }; - - dummy.Bind(Dummy.ValueProperty, binding); - return dummy.GetValue(Dummy.ValueProperty); - } - - private class Dummy : AvaloniaObject - { - public static readonly StyledProperty ValueProperty = - AvaloniaProperty.Register("Value"); - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Markups/CompositeExtension.cs b/Framework/Avalonia/Markups/CompositeExtension.cs deleted file mode 100644 index a0e00e2..0000000 --- a/Framework/Avalonia/Markups/CompositeExtension.cs +++ /dev/null @@ -1,320 +0,0 @@ -using Avalonia.Markup.Xaml; - -namespace Toolkit.Framework.Avalonia; - -public class CompositeExtension : TriggerExtension -{ - [ConstructorArgument(nameof(Triggers))] - public TriggerCollection Triggers { get; } = new TriggerCollection(); - - public CompositeExtension(object args0) - { - Triggers.Add(args0); - } - - public CompositeExtension(object args0, - object args1) - { - Triggers.Add(args0); - Triggers.Add(args1); - } - - public CompositeExtension(object args0, - object args1, - object args2) - { - Triggers.Add(args0); - Triggers.Add(args1); - Triggers.Add(args2); - } - - public CompositeExtension(object args0, - object args1, - object args2, - object args3) - { - Triggers.Add(args0); - Triggers.Add(args1); - Triggers.Add(args2); - Triggers.Add(args3); - } - - public CompositeExtension(object args0, - object args1, - object args2, - object args3, - object args4) - { - Triggers.Add(args0); - Triggers.Add(args1); - Triggers.Add(args2); - Triggers.Add(args3); - Triggers.Add(args4); - } - - public CompositeExtension(object args0, - object args1, - object args2, - object args3, - object args4, - object args5) - { - Triggers.Add(args0); - Triggers.Add(args1); - Triggers.Add(args2); - Triggers.Add(args3); - Triggers.Add(args4); - Triggers.Add(args5); - } - - public CompositeExtension(object args0, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6) - { - Triggers.Add(args0); - Triggers.Add(args1); - Triggers.Add(args2); - Triggers.Add(args3); - Triggers.Add(args4); - Triggers.Add(args5); - Triggers.Add(args6); - } - - public CompositeExtension(object args0, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7) - { - Triggers.Add(args0); - Triggers.Add(args1); - Triggers.Add(args2); - Triggers.Add(args3); - Triggers.Add(args4); - Triggers.Add(args5); - Triggers.Add(args6); - Triggers.Add(args7); - } - - public CompositeExtension(object args0, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8) - { - Triggers.Add(args0); - Triggers.Add(args1); - Triggers.Add(args2); - Triggers.Add(args3); - Triggers.Add(args4); - Triggers.Add(args5); - Triggers.Add(args6); - Triggers.Add(args7); - Triggers.Add(args8); - } - - public CompositeExtension(object args0, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9) - { - Triggers.Add(args0); - Triggers.Add(args1); - Triggers.Add(args2); - Triggers.Add(args3); - Triggers.Add(args4); - Triggers.Add(args5); - Triggers.Add(args6); - Triggers.Add(args7); - Triggers.Add(args8); - Triggers.Add(args9); - } - - public CompositeExtension(object args0, object args1, object args2, object args3, object args4, - object args5, object args6, object args7, object args8, object args9, object args10) - { - Triggers.Add(args0); - Triggers.Add(args1); - Triggers.Add(args2); - Triggers.Add(args3); - Triggers.Add(args4); - Triggers.Add(args5); - Triggers.Add(args6); - Triggers.Add(args7); - Triggers.Add(args8); - Triggers.Add(args9); - Triggers.Add(args10); - } - - public CompositeExtension(object args0, object args1, object args2, object args3, object args4, - object args5, object args6, object args7, object args8, object args9, object args10, object args11) - { - Triggers.Add(args0); - Triggers.Add(args1); - Triggers.Add(args2); - Triggers.Add(args3); - Triggers.Add(args4); - Triggers.Add(args5); - Triggers.Add(args6); - Triggers.Add(args7); - Triggers.Add(args8); - Triggers.Add(args9); - Triggers.Add(args10); - Triggers.Add(args11); - } - - public CompositeExtension(object args0, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12) - { - Triggers.Add(args0); - Triggers.Add(args1); - Triggers.Add(args2); - Triggers.Add(args3); - Triggers.Add(args4); - Triggers.Add(args5); - Triggers.Add(args6); - Triggers.Add(args7); - Triggers.Add(args8); - Triggers.Add(args9); - Triggers.Add(args10); - Triggers.Add(args11); - Triggers.Add(args12); - } - - public CompositeExtension(object args0, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12, - object args13) - { - Triggers.Add(args0); - Triggers.Add(args1); - Triggers.Add(args2); - Triggers.Add(args3); - Triggers.Add(args4); - Triggers.Add(args5); - Triggers.Add(args6); - Triggers.Add(args7); - Triggers.Add(args8); - Triggers.Add(args9); - Triggers.Add(args10); - Triggers.Add(args11); - Triggers.Add(args12); - Triggers.Add(args13); - } - - public CompositeExtension(object args0, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12, - object args13, - object args14) - { - Triggers.Add(args0); - Triggers.Add(args1); - Triggers.Add(args2); - Triggers.Add(args3); - Triggers.Add(args4); - Triggers.Add(args5); - Triggers.Add(args6); - Triggers.Add(args7); - Triggers.Add(args8); - Triggers.Add(args9); - Triggers.Add(args10); - Triggers.Add(args11); - Triggers.Add(args12); - Triggers.Add(args13); - Triggers.Add(args14); - } - - public CompositeExtension(object args0, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12, - object args13, - object args14, - object args15) - { - Triggers.Add(args0); - Triggers.Add(args1); - Triggers.Add(args2); - Triggers.Add(args3); - Triggers.Add(args4); - Triggers.Add(args5); - Triggers.Add(args6); - Triggers.Add(args7); - Triggers.Add(args8); - Triggers.Add(args9); - Triggers.Add(args10); - Triggers.Add(args11); - Triggers.Add(args12); - Triggers.Add(args13); - Triggers.Add(args14); - Triggers.Add(args15); - } - - protected override void OnInvoked(object sender, EventArgs args) - { - foreach (Delegate? trigger in Triggers) - { - trigger.Method.Invoke(trigger.Target, new object[] { sender, args }); - } - - base.OnInvoked(sender, args); - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Markups/ContentExtension.cs b/Framework/Avalonia/Markups/ContentExtension.cs deleted file mode 100644 index ac73389..0000000 --- a/Framework/Avalonia/Markups/ContentExtension.cs +++ /dev/null @@ -1,490 +0,0 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Data; -using Avalonia.Interactivity; -using Avalonia.Markup.Xaml; -using System.Diagnostics; -using Toolkit.Framework.Foundation; - -namespace Toolkit.Framework.Avalonia; - -public class ContentExtension : MarkupExtension -{ - private static readonly AttachedProperty MediatorProperty = - AvaloniaProperty.RegisterAttached("Mediator"); - - private static readonly AttachedProperty ParameterProperty = - AvaloniaProperty.RegisterAttached("Parameter"); - - private static readonly AvaloniaProperty ToProperty = - AvaloniaProperty.RegisterAttached("To"); - - private readonly Binding? mediatorBinding; - private readonly List parameters = new(); - private readonly Binding? toBinding; - - public ContentExtension(object mediator, - object to) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - } - - public ContentExtension(object mediator, - object to, - object args1) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - } - - public ContentExtension(object mediator, - object to, - object args1, - object args2) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - } - - public ContentExtension(object mediator, - object to, - object args1, - object args2, - object args3) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - } - - public ContentExtension(object mediator, - object to, - object args1, - object args2, - object args3, - object args4) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - } - - public ContentExtension(object mediator, - object to, - object args1, - object args2, - object args3, - object args4, - object args5) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - } - - public ContentExtension(object mediator, - object to, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - } - - public ContentExtension(object mediator, - object to, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - } - - public ContentExtension(object mediator, - object to, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - } - - public ContentExtension(object mediator, - object to, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - } - - public ContentExtension(object mediator, - object to, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - } - - public ContentExtension(object mediator, - object to, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - parameters.Add(args11 is MarkupExtension ? args11 : args11.ToBinding()); - } - - public ContentExtension(object mediator, - object to, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - parameters.Add(args11 is MarkupExtension ? args11 : args11.ToBinding()); - parameters.Add(args12 is MarkupExtension ? args12 : args12.ToBinding()); - } - - public ContentExtension(object mediator, - object to, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12, - object args13) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - parameters.Add(args11 is MarkupExtension ? args11 : args11.ToBinding()); - parameters.Add(args12 is MarkupExtension ? args12 : args12.ToBinding()); - parameters.Add(args13 is MarkupExtension ? args13 : args13.ToBinding()); - } - - public ContentExtension(object mediator, - object to, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12, - object args13, - object args14) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - parameters.Add(args11 is MarkupExtension ? args11 : args11.ToBinding()); - parameters.Add(args12 is MarkupExtension ? args12 : args12.ToBinding()); - parameters.Add(args13 is MarkupExtension ? args13 : args13.ToBinding()); - parameters.Add(args14 is MarkupExtension ? args14 : args14.ToBinding()); - } - - public ContentExtension(object mediator, - object to, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12, - object args13, - object args14, - object args15) - { - mediatorBinding = mediator.ToBinding(); - this.toBinding = to is Binding toBinding ? toBinding : to.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - parameters.Add(args11 is MarkupExtension ? args11 : args11.ToBinding()); - parameters.Add(args12 is MarkupExtension ? args12 : args12.ToBinding()); - parameters.Add(args13 is MarkupExtension ? args13 : args13.ToBinding()); - parameters.Add(args14 is MarkupExtension ? args14 : args14.ToBinding()); - parameters.Add(args15 is MarkupExtension ? args15 : args15.ToBinding()); - } - - public override object? ProvideValue(IServiceProvider serviceProvider) - { - if (serviceProvider.GetService(typeof(IProvideValueTarget)) is IProvideValueTarget target) - { - AvaloniaObject? targetObject = null; - if (target.TargetObject is AvaloniaObject avaloniaObject) - { - targetObject = avaloniaObject; - } - else if (serviceProvider.GetService(typeof(IRootObjectProvider)) is IRootObjectProvider root) - { - targetObject = (AvaloniaObject)root.RootObject; - } - - if (targetObject is not null && toBinding is not null && mediatorBinding is not null) - { - if (target.TargetProperty is StyledProperty targetProperty) - { - if (targetObject is Control control) - { - void SetContent() - { - targetObject.Bind(MediatorProperty, mediatorBinding); - if (targetObject.GetValue(MediatorProperty) is IMediator mediator) - { - targetObject.Bind(ToProperty, toBinding); - if (targetObject.GetValue(ToProperty) is { } to) - { - List? parameters = new(); - foreach (object? parameter in this.parameters) - { - if (parameter is not null) - { - switch (parameter) - { - case IParameter keyedParameter: - if (keyedParameter.GetValue(targetObject) is KeyValuePair keyValuePair) - { - parameters.Add(keyValuePair); - } - break; - - default: - if (parameter.ToBinding() is Binding defaultDinding) - { - targetObject.Bind(ParameterProperty, defaultDinding); - parameters.Add((dynamic)targetObject.GetValue(ParameterProperty)); - } - break; - } - } - } - - if (to is string name) - { - Trace.WriteLine(name); - - ValueTask namedTask = mediator.Send(new Content(name, parameters.ToArray())); - if (namedTask is ValueTask { Result: object result }) - { - control.SetValue(targetProperty, result); - } - } - - if (to is Type type) - { - ValueTask typedTask = mediator.Send(new Content(type, parameters.ToArray())); - if (typedTask is ValueTask { Result: object result }) - { - control.SetValue(targetProperty, result); - } - } - } - } - } - - if (!control.IsLoaded) - { - void HandleLoaded(object? sender, RoutedEventArgs args) - { - control.Loaded -= HandleLoaded; - SetContent(); - } - - control.Loaded += HandleLoaded; - } - else - { - SetContent(); - } - } - } - } - } - - return default; - } -} diff --git a/Framework/Avalonia/Markups/EventParameterExtension.cs b/Framework/Avalonia/Markups/EventParameterExtension.cs deleted file mode 100644 index 7605e2f..0000000 --- a/Framework/Avalonia/Markups/EventParameterExtension.cs +++ /dev/null @@ -1,64 +0,0 @@ -using Avalonia.Data.Converters; -using Avalonia.Markup.Xaml; -using Toolkit.Framework.Foundation; - -namespace Toolkit.Framework.Avalonia; - -public class EventParameterExtension : MarkupExtension, IEventParameter -{ - private readonly IValueConverter? converter; - - private readonly object? converterParameter; - - private readonly string? key; - private readonly string? path; - - public EventParameterExtension() - { - } - - public EventParameterExtension(string key, string path) - { - this.key = key; - this.path = path; - } - - public EventParameterExtension(string path) - { - this.path = path; - } - - public EventParameterExtension(IValueConverter? converter = null, object? converterParameter = null) - { - this.converter = converter; - this.converterParameter = converterParameter; - } - - public List GetValues(EventArgs args) - { - List? parameters = new(); - - dynamic? arguments = args.GetEventArguments(path, converter, converterParameter); - if (arguments is not null) - { - if (arguments is ICollection collection) - { - foreach (object? argument in collection) - { - parameters.Add(key is not null ? new KeyValuePair(key, (dynamic)argument) : argument); - } - } - else - { - parameters.Add(key is not null ? new KeyValuePair(key, arguments) : arguments); - } - } - - return parameters; - } - - public override object ProvideValue(IServiceProvider serviceProvider) - { - return this; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Markups/InvokeExtension.cs b/Framework/Avalonia/Markups/InvokeExtension.cs deleted file mode 100644 index 3ceb987..0000000 --- a/Framework/Avalonia/Markups/InvokeExtension.cs +++ /dev/null @@ -1,423 +0,0 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Data; -using Avalonia.Markup.Xaml; -using System.Diagnostics.CodeAnalysis; -using System.Reflection; - -namespace Toolkit.Framework.Avalonia; - -public class InvokeExtension : TriggerExtension -{ - private static readonly AvaloniaProperty TargetProperty = - AvaloniaProperty.RegisterAttached("Target"); - - private readonly object path; - private readonly List parameters = new(); - - public InvokeExtension(object path) - { - this.path = path; - } - - public InvokeExtension(object path, - object args1) - { - this.path = path; - - parameters.Add(args1 is not MarkupExtension ? args1.ToBinding() : args1); - } - - public InvokeExtension(object path, - object args1, - object args2) - { - this.path = path; - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - } - - public InvokeExtension(object path, - object args1, - object args2, - object args3) - { - this.path = path; - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - } - - public InvokeExtension(object path, - object args1, - object args2, - object args3, - object args4) - { - this.path = path; - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - } - - public InvokeExtension(object path, - object args1, - object args2, - object args3, - object args4, - object args5) - { - this.path = path; - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - } - - public InvokeExtension(object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6) - { - this.path = path; - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - } - - public InvokeExtension(object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7) - { - this.path = path; - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - } - - public InvokeExtension(object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8) - { - this.path = path; - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - } - - public InvokeExtension(object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9) - { - this.path = path; - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - } - - public InvokeExtension(object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10) - { - this.path = path; - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - } - - public InvokeExtension(object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11) - { - this.path = path; - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - parameters.Add(args11 is MarkupExtension ? args11 : args11.ToBinding()); - } - - public InvokeExtension(object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12) - { - this.path = path; - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - parameters.Add(args11 is MarkupExtension ? args11 : args11.ToBinding()); - parameters.Add(args12 is MarkupExtension ? args12 : args12.ToBinding()); - } - - public InvokeExtension(object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12, - object args13) - { - this.path = path; - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - parameters.Add(args11 is MarkupExtension ? args11 : args11.ToBinding()); - parameters.Add(args12 is MarkupExtension ? args12 : args12.ToBinding()); - parameters.Add(args13 is MarkupExtension ? args13 : args13.ToBinding()); - } - - public InvokeExtension(object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12, - object args13, - object args14) - { - this.path = path; - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - parameters.Add(args11 is MarkupExtension ? args11 : args11.ToBinding()); - parameters.Add(args12 is MarkupExtension ? args12 : args12.ToBinding()); - parameters.Add(args13 is MarkupExtension ? args13 : args13.ToBinding()); - parameters.Add(args14 is MarkupExtension ? args14 : args14.ToBinding()); - } - - public InvokeExtension(object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12, - object args13, - object args14, - object args15) - { - this.path = path; - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - parameters.Add(args11 is MarkupExtension ? args11 : args11.ToBinding()); - parameters.Add(args12 is MarkupExtension ? args12 : args12.ToBinding()); - parameters.Add(args13 is MarkupExtension ? args13 : args13.ToBinding()); - parameters.Add(args14 is MarkupExtension ? args14 : args14.ToBinding()); - parameters.Add(args15 is MarkupExtension ? args15 : args15.ToBinding()); - } - - protected override void OnInvoked(object sender, EventArgs args) - { - if (sender is AvaloniaObject avaloniaObject) - { - CreaterHandler(avaloniaObject, args); - } - } - - private void CreaterHandler(AvaloniaObject sender, EventArgs args) - { - if (TryGetInvoke(sender, out (object? Target, MethodInfo? MethodInfo) invoker)) - { - if (invoker.Target is object target) - { - if (invoker.MethodInfo is MethodInfo methodInfo) - { - ParameterInfo[] parameterInfo = methodInfo.GetParameters(); - List parameters = new(); - - foreach (object? parameter in this.parameters) - { - switch (parameter) - { - //case IParameter keyedParameter: - // BindingOperations.SetBinding(sender, ParameterProperty, parameter.ToBinding()); - // parameters.Add(new KeyValuePair(keyedParameter.Key, (dynamic)sender.GetValue(ParameterProperty))); - // break; - //case IEventParameter eventParameter: - // parameters.AddRange(eventParameter.GetParameters(args)); - // break; - //default: - // BindingOperations.SetBinding(sender, ParameterProperty, parameter.ToBinding()); - // parameters.Add((dynamic)sender.GetValue(ParameterProperty)); - // break; - } - } - - methodInfo.Invoke(target, parameters.Any() ? parameters.ToArray() : parameterInfo.Length > 0 ? new object?[] { null } : Array.Empty()); - } - } - } - } - - private bool TryGetInvoke(AvaloniaObject sender, [AllowNull] out (object?, MethodInfo?) invoker) - { - if (path is Binding binding) - { - sender.Bind(TargetProperty, binding); - if (sender.GetValue(TargetProperty) is Action action) - { - invoker = new(action.Target, action.Method); - return true; - } - } - - if (path is string name) - { - if (sender.GetValue(StyledElement.DataContextProperty) is object dataContext) - { - if (dataContext.GetType().GetMethod(name, BindingFlags.Public | BindingFlags.Instance) is MethodInfo methodInfo) - { - invoker = new(dataContext, methodInfo); - return true; - } - } - } - - invoker = default; - return false; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Markups/NavigateExtension.cs b/Framework/Avalonia/Markups/NavigateExtension.cs deleted file mode 100644 index d53ec67..0000000 --- a/Framework/Avalonia/Markups/NavigateExtension.cs +++ /dev/null @@ -1,445 +0,0 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Data; -using Avalonia.Markup.Xaml; -using System.Xml.Linq; -using Toolkit.Framework.Foundation; - -namespace Toolkit.Framework.Avalonia; -public class NavigateExtension : TriggerExtension -{ - private static readonly AttachedProperty MediatorProperty = - AvaloniaProperty.RegisterAttached("Mediator"); - - private static readonly AttachedProperty ParameterProperty = - AvaloniaProperty.RegisterAttached("Parameter"); - - private static readonly AvaloniaProperty PathProperty = - AvaloniaProperty.RegisterAttached("Path"); - - private readonly Binding? mediatorBinding; - private readonly List parameters = new(); - private readonly Binding? pathBinding; - - public NavigateExtension(object mediator, - object path) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - } - - public NavigateExtension(object mediator, - object path, - object args1) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - } - - public NavigateExtension(object mediator, - object path, - object args1, - object args2) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - } - - public NavigateExtension(object mediator, - object path, - object args1, - object args2, - object args3) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - } - - public NavigateExtension(object mediator, - object path, - object args1, - object args2, - object args3, - object args4) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - } - - public NavigateExtension(object mediator, - object path, - object args1, - object args2, - object args3, - object args4, - object args5) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - } - - public NavigateExtension(object mediator, - object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - } - - public NavigateExtension(object mediator, - object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - } - - public NavigateExtension(object mediator, - object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - } - - public NavigateExtension(object mediator, - object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - } - - public NavigateExtension(object mediator, - object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - } - - public NavigateExtension(object mediator, - object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - parameters.Add(args11 is MarkupExtension ? args11 : args11.ToBinding()); - } - - public NavigateExtension(object mediator, - object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - parameters.Add(args11 is MarkupExtension ? args11 : args11.ToBinding()); - parameters.Add(args12 is MarkupExtension ? args12 : args12.ToBinding()); - } - - public NavigateExtension(object mediator, - object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12, - object args13) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - parameters.Add(args11 is MarkupExtension ? args11 : args11.ToBinding()); - parameters.Add(args12 is MarkupExtension ? args12 : args12.ToBinding()); - parameters.Add(args13 is MarkupExtension ? args13 : args13.ToBinding()); - } - - public NavigateExtension(object mediator, - object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12, - object args13, - object args14) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - parameters.Add(args11 is MarkupExtension ? args11 : args11.ToBinding()); - parameters.Add(args12 is MarkupExtension ? args12 : args12.ToBinding()); - parameters.Add(args13 is MarkupExtension ? args13 : args13.ToBinding()); - parameters.Add(args14 is MarkupExtension ? args14 : args14.ToBinding()); - } - - public NavigateExtension(object mediator, - object path, - object args1, - object args2, - object args3, - object args4, - object args5, - object args6, - object args7, - object args8, - object args9, - object args10, - object args11, - object args12, - object args13, - object args14, - object args15) - { - mediatorBinding = mediator.ToBinding(); - this.pathBinding = path is Binding pathBinding ? pathBinding : path.ToBinding(); - - parameters.Add(args1 is MarkupExtension ? args1 : args1.ToBinding()); - parameters.Add(args2 is MarkupExtension ? args2 : args2.ToBinding()); - parameters.Add(args3 is MarkupExtension ? args3 : args3.ToBinding()); - parameters.Add(args4 is MarkupExtension ? args4 : args4.ToBinding()); - parameters.Add(args5 is MarkupExtension ? args5 : args5.ToBinding()); - parameters.Add(args6 is MarkupExtension ? args6 : args6.ToBinding()); - parameters.Add(args7 is MarkupExtension ? args7 : args7.ToBinding()); - parameters.Add(args8 is MarkupExtension ? args8 : args8.ToBinding()); - parameters.Add(args9 is MarkupExtension ? args9 : args9.ToBinding()); - parameters.Add(args10 is MarkupExtension ? args10 : args10.ToBinding()); - parameters.Add(args11 is MarkupExtension ? args11 : args11.ToBinding()); - parameters.Add(args12 is MarkupExtension ? args12 : args12.ToBinding()); - parameters.Add(args13 is MarkupExtension ? args13 : args13.ToBinding()); - parameters.Add(args14 is MarkupExtension ? args14 : args14.ToBinding()); - parameters.Add(args15 is MarkupExtension ? args15 : args15.ToBinding()); - } - - protected override void OnInvoked(object sender, EventArgs args) - { - if (TargetObject is not null && mediatorBinding is not null) - { - TargetObject.Bind(MediatorProperty, mediatorBinding); - if (TargetObject.GetValue(MediatorProperty) is IMediator mediator) - { - if (pathBinding is not null) - { - TargetObject.Bind(PathProperty, pathBinding); - if (TargetObject.GetValue(PathProperty) is string path) - { - List? parameters = new(); - foreach (object? parameter in this.parameters) - { - if (parameter is not null) - { - switch (parameter) - { - case IParameter keyedParameter: - if (keyedParameter.GetValue(TargetObject) is KeyValuePair keyValuePair) - { - parameters.Add(keyValuePair); - } - break; - - case IEventParameter eventParameter: - parameters.AddRange(eventParameter.GetValues(args)); - break; - - default: - if (parameter.ToBinding() is Binding defaultDinding) - { - TargetObject.Bind(ParameterProperty, defaultDinding); - parameters.Add((dynamic)TargetObject.GetValue(ParameterProperty)); - } - break; - } - } - } - - if (pathBinding?.StringFormat is string format) - { - path = string.Format(format, path); - } - - mediator.Send(new Navigate(path, parameters.ToArray())); - } - } - } - - base.OnInvoked(sender, args); - } - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Markups/NavigationRouteExtension.cs b/Framework/Avalonia/Markups/NavigationRouteExtension.cs deleted file mode 100644 index b1adf7b..0000000 --- a/Framework/Avalonia/Markups/NavigationRouteExtension.cs +++ /dev/null @@ -1,90 +0,0 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Controls.Primitives; -using Avalonia.Data; -using Avalonia.Interactivity; -using Avalonia.Markup.Xaml; -using Toolkit.Framework.Foundation; - -namespace Toolkit.Framework.Avalonia; - -public class NavigationRouteExtension : MarkupExtension -{ - private static readonly AttachedProperty MediatorProperty = - AvaloniaProperty.RegisterAttached("Mediator"); - - private readonly string name; - private readonly Binding? mediatorBinding; - - public NavigationRouteExtension(object mediator, string name) - { - mediatorBinding = mediator is Binding toBinding ? toBinding : mediator.ToBinding(); - this.name = name; - } - - private bool TryGetBinding(AvaloniaObject sender, out object? binding) - { - binding = sender.GetValue(StyledElement.DataContextProperty); - return binding is not null; - } - - public override object? ProvideValue(IServiceProvider serviceProvider) - { - if (serviceProvider.GetService(typeof(IProvideValueTarget)) is IProvideValueTarget target) - { - if (target.TargetObject is TemplatedControl control) - { - if (!TryGetBinding(control, out object? binding)) - { - void AddRoute(TemplatedControl control) - { - if (mediatorBinding is not null) - { - control.Bind(MediatorProperty, mediatorBinding); - if (control.GetValue(MediatorProperty) is IMediator mediator) - { - mediator.Send(new NavigationRoute(name, control)); - control.ClearValue(MediatorProperty); - } - } - } - - void HandleDataContextChanged(object? sender, EventArgs args) - { - control.Loaded -= HandleLoaded; - if (TryGetBinding(control, out binding)) - { - AddRoute(control); - } - } - - control.DataContextChanged += HandleDataContextChanged; - void HandleLoaded(object? sender, RoutedEventArgs args) - { - control.Loaded -= HandleLoaded; - if (TryGetBinding(control, out binding)) - { - AddRoute(control); - } - } - - control.Loaded += HandleLoaded; - } - else - { - if (mediatorBinding is not null) - { - control.Bind(MediatorProperty, mediatorBinding); - if (control.GetValue(MediatorProperty) is IMediator mediator) - { - mediator.Send(new NavigationRoute(name, control)); - control.ClearValue(MediatorProperty); - } - } - } - } - } - - return null; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Markups/ParameterBindingExtension.cs b/Framework/Avalonia/Markups/ParameterBindingExtension.cs deleted file mode 100644 index 97c73c3..0000000 --- a/Framework/Avalonia/Markups/ParameterBindingExtension.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Data; -using Avalonia.Markup.Xaml; -using Toolkit.Framework.Foundation; - -namespace Toolkit.Framework.Avalonia; - -public class ParameterBindingExtension : MarkupExtension, IParameter -{ - private static readonly AttachedProperty ValueProperty = - AvaloniaProperty.RegisterAttached("Value"); - - private readonly Binding? valueBinding; - - public ParameterBindingExtension(string key, object value) - { - Key = key; - valueBinding = value.ToBinding(); - } - - public string? Key { get; } - - public KeyValuePair? GetValue(object target) - { - if (target is AvaloniaObject avaloniaObject) - { - if (valueBinding is not null) - { - avaloniaObject.Bind(ValueProperty, valueBinding); - return new KeyValuePair(Key, (dynamic)avaloniaObject.GetValue(ValueProperty)); - } - } - - return default; - } - - public override object ProvideValue(IServiceProvider serviceProvider) - { - return this; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Markups/TriggerCollection.cs b/Framework/Avalonia/Markups/TriggerCollection.cs deleted file mode 100644 index 8e60015..0000000 --- a/Framework/Avalonia/Markups/TriggerCollection.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.ObjectModel; - -namespace Toolkit.Framework.Avalonia; - -public class TriggerCollection : Collection -{ - public void Add(object item) - { - if (item is Delegate trigger) - { - base.Add(trigger); - } - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Markups/TriggerExtension.cs b/Framework/Avalonia/Markups/TriggerExtension.cs deleted file mode 100644 index 7474e2b..0000000 --- a/Framework/Avalonia/Markups/TriggerExtension.cs +++ /dev/null @@ -1,71 +0,0 @@ -using Avalonia; -using Avalonia.Markup.Xaml; -using System.Reflection; - -namespace Toolkit.Framework.Avalonia; - -public class TriggerExtension : MarkupExtension -{ - public AvaloniaObject? TargetObject { get; protected set; } - - protected object? TargetInvoke { get; private set; } - - public void Invoke(object sender, EventArgs args) - { - OnInvoked(sender, args); - } - - public override object? ProvideValue(IServiceProvider serviceProvider) - { - if (serviceProvider.GetService(typeof(IProvideValueTarget)) is IProvideValueTarget target) - { - if (target.TargetObject is AvaloniaObject avaloniaObject) - { - TargetObject = avaloniaObject; - } - else if (serviceProvider.GetService(typeof(IRootObjectProvider)) is IRootObjectProvider root) - { - TargetObject = (AvaloniaObject)root.RootObject; - } - - if (TargetObject is not null) - { - string? targetName = target.TargetProperty as string; - TargetInvoke = target.TargetProperty; - OnAttached(serviceProvider); - - EventInfo? eventInfo = target.TargetProperty as EventInfo ?? (targetName is not null ? TargetObject.GetType().GetEvent(targetName) : null); - MethodInfo? methodInfo = eventInfo is not null ? null : target.TargetProperty as MethodInfo ?? (targetName is not null ? TargetObject.GetType().GetMethod(targetName) : null); - - MethodInfo invokeMethod = GetType().GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public)!; - if (invokeMethod is null) - { - return this; - } - - if (eventInfo is not null) - { - return Delegate.CreateDelegate(eventInfo.EventHandlerType!, this, invokeMethod); - } - - if (methodInfo is not null) - { - if (methodInfo.GetParameters() is ParameterInfo[] methodParameters && methodParameters is { Length: 2 }) - { - return Delegate.CreateDelegate(methodParameters[1].ParameterType, this, invokeMethod); - } - } - } - } - - return default; - } - - protected virtual void OnAttached(IServiceProvider serviceProvider) - { - } - - protected virtual void OnInvoked(object sender, EventArgs args) - { - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Navigation/ContentControlNavigation.cs b/Framework/Avalonia/Navigation/ContentControlNavigation.cs deleted file mode 100644 index 82a4f3e..0000000 --- a/Framework/Avalonia/Navigation/ContentControlNavigation.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Controls; - -namespace Toolkit.Framework.Avalonia; - -public record ContentControlNavigation : Navigation -{ - public ContentControlNavigation(ContentControl route, - object? content, - object? template, - IDictionary? parameters) : base(route, content, template, parameters) - { - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Navigation/ContentControlNavigationHandler.cs b/Framework/Avalonia/Navigation/ContentControlNavigationHandler.cs deleted file mode 100644 index cd72723..0000000 --- a/Framework/Avalonia/Navigation/ContentControlNavigationHandler.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Avalonia.Controls.Primitives; -using Toolkit.Framework.Foundation; - -namespace Toolkit.Framework.Avalonia; - -public class ContentControlNavigationHandler : IRequestHandler -{ - public ValueTask Handle(ContentControlNavigation request, CancellationToken cancellationToken) - { - if (request.Template is TemplatedControl control) - { - control.DataContext = request.Content; - request.Route.Content = control; - } - - return default; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Navigation/ContentDialogNavigation.cs b/Framework/Avalonia/Navigation/ContentDialogNavigation.cs deleted file mode 100644 index 3ed4540..0000000 --- a/Framework/Avalonia/Navigation/ContentDialogNavigation.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FluentAvalonia.UI.Controls; - -namespace Toolkit.Framework.Avalonia; - -public record ContentDialogNavigation : Navigation -{ - public ContentDialogNavigation(ContentDialog route, - object? content, - object? template, - IDictionary? parameters) : base(route, content, template, parameters) - { - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Navigation/ContentDialogNavigationHandler.cs b/Framework/Avalonia/Navigation/ContentDialogNavigationHandler.cs deleted file mode 100644 index d4bbed2..0000000 --- a/Framework/Avalonia/Navigation/ContentDialogNavigationHandler.cs +++ /dev/null @@ -1,45 +0,0 @@ -using FluentAvalonia.UI.Controls; -using System.Diagnostics; -using Toolkit.Framework.Foundation; - -namespace Toolkit.Framework.Avalonia; - -public class ContentDialogNavigationHandler : IRequestHandler -{ - public ValueTask Handle(ContentDialogNavigation request, CancellationToken cancellationToken) - { - if (request.Template is ContentDialog contentDialog) - { - async void HandleButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args) - { - ContentDialogButtonClickDeferral defferal = args.GetDeferral(); - if (sender.DataContext is INavigationConfirmation confirmation) - { - if (!await confirmation.CanConfirm()) - { - args.Cancel = true; - } - } - - if (!args.Cancel) - { - contentDialog.SecondaryButtonClick -= HandleButtonClick; - contentDialog.PrimaryButtonClick -= HandleButtonClick; - contentDialog.CloseButtonClick -= HandleButtonClick; - } - - defferal.Complete(); - } - - contentDialog.SecondaryButtonClick += HandleButtonClick; - contentDialog.PrimaryButtonClick += HandleButtonClick; - contentDialog.CloseButtonClick += HandleButtonClick; - - contentDialog.DataContext = request.Content; - - contentDialog.ShowAsync(); - } - - return default; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Navigation/FrameNavigation.cs b/Framework/Avalonia/Navigation/FrameNavigation.cs deleted file mode 100644 index 28c00b7..0000000 --- a/Framework/Avalonia/Navigation/FrameNavigation.cs +++ /dev/null @@ -1,14 +0,0 @@ -using FluentAvalonia.UI.Controls; - -namespace Toolkit.Framework.Avalonia; - -public record FrameNavigation : Navigation -{ - public FrameNavigation(Frame route, - object? content, - object? template, - IDictionary? - parameters) : base(route, content, template, parameters) - { - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Navigation/FrameNavigationHandler.cs b/Framework/Avalonia/Navigation/FrameNavigationHandler.cs deleted file mode 100644 index 5eab458..0000000 --- a/Framework/Avalonia/Navigation/FrameNavigationHandler.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Avalonia.Controls.Primitives; -using FluentAvalonia.UI.Navigation; -using Toolkit.Framework.Foundation; - -namespace Toolkit.Framework.Avalonia; - -public class FrameNavigationHandler : IRequestHandler -{ - public ValueTask Handle(FrameNavigation request, CancellationToken cancellationToken) - { - request.Route.NavigationPageFactory = new NavigationPageFactory(); - - TaskCompletionSource completionSource = new(); - if (request.Template is TemplatedControl content) - { - void HandleNavigated(object sender, NavigationEventArgs args) - { - request.Route.Navigated -= HandleNavigated; - if (request.Route.Content is TemplatedControl control) - { - control.DataContext = request.Content; - completionSource.SetResult(true); - } - } - - request.Route.Navigated += HandleNavigated; - request.Route.NavigateFromObject(content); - } - - return default; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Navigation/NavigateBackHandler.cs b/Framework/Avalonia/Navigation/NavigateBackHandler.cs deleted file mode 100644 index 1e4e4d3..0000000 --- a/Framework/Avalonia/Navigation/NavigateBackHandler.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Avalonia.Controls; -using Avalonia.Controls.Primitives; -using FluentAvalonia.UI.Controls; -using Toolkit.Framework.Foundation; - -namespace Toolkit.Framework.Avalonia; - -public class NavigateBackHandler : IRequestHandler -{ - private readonly INavigationRouteDescriptorCollection descriptors; - - public NavigateBackHandler(INavigationRouteDescriptorCollection descriptors) - { - this.descriptors = descriptors; - } - - public ValueTask Handle(NavigateBack request, CancellationToken cancellationToken) - { - if (descriptors.FirstOrDefault(x => request.Route is string { } name && name == x.Name) is NavigationRouteDescriptor descriptor) - { - if (descriptor.Route is ContentControl { Content: TemplatedControl content }) - { - if (content.DataContext is IDisposable disposable) - { - disposable.Dispose(); - } - } - - if (descriptor.Route is Frame frame) - { - frame.GoBack(); - } - } - - return default; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Navigation/NavigateHandler.cs b/Framework/Avalonia/Navigation/NavigateHandler.cs deleted file mode 100644 index e7aa658..0000000 --- a/Framework/Avalonia/Navigation/NavigateHandler.cs +++ /dev/null @@ -1,103 +0,0 @@ -using Avalonia.Controls; -using Toolkit.Controls.Avalonia; -using Toolkit.Framework.Foundation; -using Microsoft.Extensions.Primitives; -using System.Diagnostics; - -namespace Toolkit.Framework.Avalonia; - -public class NavigateHandler : IRequestHandler -{ - private readonly INavigationRouteDescriptorCollection descriptors; - private readonly IMediator mediator; - private readonly INamedContentTemplateFactory namedContentTemplateFactory; - private readonly INamedContentFactory namedContentFactory; - private readonly IContentTemplateFactory contentTemplateFactory; - private readonly ITypedContentFactory typedContentFactory; - - public NavigateHandler(IMediator mediator, - IContentTemplateFactory contentTemplateFactory, - INamedContentFactory namedContentFactory, - INamedContentTemplateFactory namedContentTemplateFactory, - ITypedContentFactory typedContentFactory, - INavigationRouteDescriptorCollection descriptors) - { - this.mediator = mediator; - this.contentTemplateFactory = contentTemplateFactory; - this.namedContentFactory = namedContentFactory; - this.namedContentTemplateFactory = namedContentTemplateFactory; - this.typedContentFactory = typedContentFactory; - this.descriptors = descriptors; - } - - public ValueTask Handle(Navigate request, CancellationToken cancellationToken) - { - foreach (NavigationSegment segment in NavigationSegment.FromPath(request.Path)) - { - object? content = null; - object? template = null; - - Dictionary keyedParameters = new(); - List parameters = new(); - - foreach (object? parameter in request.Parameters) - { - if (parameter is not null) - { - if (parameter is KeyValuePair keyed) - { - keyedParameters.Add(keyed.Key, keyed.Value); - } - else - { - parameters.Add(parameter); - } - } - } - - if (segment.Name is { Length: > 0 } name) - { - content = namedContentFactory.Create(name, parameters.ToArray()); - template = namedContentTemplateFactory.Create(name); - } - - if (template is not null) - { - object? target = null; - if (descriptors.FirstOrDefault(x => segment.Target is string { } name && name == x.Name) is NavigationRouteDescriptor descriptor) - { - target = descriptor.Route; - } - else - { - target = template; - } - - if (target is Frame frame) - { - mediator.Send(new FrameNavigation(frame, content, template, keyedParameters)); - } - else if (target is ContentDialog dialog) - { - mediator.Send(new ContentDialogNavigation(dialog, content, template, keyedParameters)); - } - else if (target is ContentControl contentControl) - { - mediator.Send(new ContentControlNavigation(contentControl, content, template, keyedParameters)); - } - } - else - { - if (descriptors.FirstOrDefault(x => segment.Target is string { } name && name == x.Name) is NavigationRouteDescriptor descriptor) - { - if (descriptor.Route is ContentControl contentControl) - { - contentControl.Content = null; - } - } - } - } - - return default; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Navigation/Navigation.cs b/Framework/Avalonia/Navigation/Navigation.cs deleted file mode 100644 index 4a86937..0000000 --- a/Framework/Avalonia/Navigation/Navigation.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Avalonia.Controls.Primitives; -using Toolkit.Framework.Foundation; - -namespace Toolkit.Framework.Avalonia; - -public record Navigation : IRequest where TRoute : TemplatedControl -{ - public TRoute Route { get; } - - public Navigation(TRoute route, - object? content, - object? template, - IDictionary? parameters) - { - Route = route; - Content = content; - Template = template; - Parameters = parameters; - } - - public object? Content { get; } - - public object? Template { get; } - - public IDictionary? Parameters { get; } -} \ No newline at end of file diff --git a/Framework/Avalonia/Navigation/NavigationPageFactory.cs b/Framework/Avalonia/Navigation/NavigationPageFactory.cs deleted file mode 100644 index 109fd52..0000000 --- a/Framework/Avalonia/Navigation/NavigationPageFactory.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Avalonia.Controls; -using FluentAvalonia.UI.Controls; - -namespace Toolkit.Framework.Avalonia; - -internal class NavigationPageFactory : INavigationPageFactory -{ - public IControl? GetPage(Type srcType) - { - return default; - } - - public IControl GetPageFromObject(object target) - { - return (IControl)target; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Navigation/NavigationRouteHandler.cs b/Framework/Avalonia/Navigation/NavigationRouteHandler.cs deleted file mode 100644 index 144a717..0000000 --- a/Framework/Avalonia/Navigation/NavigationRouteHandler.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Avalonia.Controls.Primitives; -using Avalonia.Interactivity; -using Toolkit.Framework.Foundation; - -namespace Toolkit.Framework.Avalonia; - -public class NavigationRouteHandler : IRequestHandler -{ - private readonly INavigationRouteDescriptorCollection descriptors; - - public NavigationRouteHandler(INavigationRouteDescriptorCollection descriptors) - { - this.descriptors = descriptors; - } - - public ValueTask Handle(NavigationRoute request, CancellationToken cancellationToken) - { - if (request.Route is TemplatedControl control) - { - void HandleUnloaded(object? sender, RoutedEventArgs args) - { - if (descriptors.FirstOrDefault(x => x.Route == sender) is INavigationRouteDescriptor descriptor) - { - descriptors.Remove(descriptor); - } - } - control.Unloaded += HandleUnloaded; - } - - if (descriptors.FirstOrDefault(x => x.Name == request.Name) is INavigationRouteDescriptor descriptor) - { - descriptors.Remove(descriptor); - } - - descriptors.Add(new NavigationRouteDescriptor(request.Name, request.Route)); - return default; - } -} \ No newline at end of file diff --git a/Framework/Avalonia/Properties/Assembly.cs b/Framework/Avalonia/Properties/Assembly.cs deleted file mode 100644 index 135543a..0000000 --- a/Framework/Avalonia/Properties/Assembly.cs +++ /dev/null @@ -1,3 +0,0 @@ -using Avalonia.Metadata; - -[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Toolkit.Framework.Avalonia")] \ No newline at end of file diff --git a/Framework/Foundation/Configurations/ConfigurationChanged.cs b/Framework/Foundation/Configurations/ConfigurationChanged.cs deleted file mode 100644 index bd03b1e..0000000 --- a/Framework/Foundation/Configurations/ConfigurationChanged.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public record ConfigurationChanged(TConfiguration Configuration) : INotification where TConfiguration : class; \ No newline at end of file diff --git a/Framework/Foundation/Configurations/ConfigurationInitializer.cs b/Framework/Foundation/Configurations/ConfigurationInitializer.cs deleted file mode 100644 index 86a82ff..0000000 --- a/Framework/Foundation/Configurations/ConfigurationInitializer.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public class ConfigurationInitializer : IInitializable where TConfiguration : class, new() -{ - private readonly TConfiguration configuration; - private readonly IMediator mediator; - - public ConfigurationInitializer(TConfiguration configuration, - IMediator mediator) - { - this.configuration = configuration; - this.mediator = mediator; - } - - public async Task InitializeAsync() - { - await mediator.Send(configuration); - await Task.CompletedTask; - } -} \ No newline at end of file diff --git a/Framework/Foundation/Configurations/ConfigurationWriter.cs b/Framework/Foundation/Configurations/ConfigurationWriter.cs deleted file mode 100644 index b953116..0000000 --- a/Framework/Foundation/Configurations/ConfigurationWriter.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.Extensions.Configuration; - -namespace Toolkit.Framework.Foundation; - -public class ConfigurationWriter : IConfigurationWriter where TConfiguration : class, new() -{ - private readonly IConfiguration rootConfiguration; - private readonly string section; - - public ConfigurationWriter(IConfiguration rootConfiguration, string section) - { - this.rootConfiguration = rootConfiguration; - this.section = section; - } - - public void Write(TConfiguration configuration) - { - if (rootConfiguration is IConfigurationRoot root) - { - foreach (IConfigurationProvider? provider in root.Providers) - { - if (provider is IWritableConfigurationProvider writableConfigurationProvider) - { - writableConfigurationProvider.Write(section, configuration); - } - } - } - } -} \ No newline at end of file diff --git a/Framework/Foundation/Configurations/IConfigurationWriter.cs b/Framework/Foundation/Configurations/IConfigurationWriter.cs deleted file mode 100644 index 866660c..0000000 --- a/Framework/Foundation/Configurations/IConfigurationWriter.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IConfigurationWriter where TConfiguration : class -{ - void Write(TConfiguration args); -} \ No newline at end of file diff --git a/Framework/Foundation/Configurations/IWritableConfigurationProvider.cs b/Framework/Foundation/Configurations/IWritableConfigurationProvider.cs deleted file mode 100644 index 44dd4c5..0000000 --- a/Framework/Foundation/Configurations/IWritableConfigurationProvider.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IWritableConfigurationProvider -{ - void Write(string section, TValue value) where TValue : class, new(); -} \ No newline at end of file diff --git a/Framework/Foundation/Configurations/IWritableJsonConfigurationBuilder.cs b/Framework/Foundation/Configurations/IWritableJsonConfigurationBuilder.cs deleted file mode 100644 index 061a498..0000000 --- a/Framework/Foundation/Configurations/IWritableJsonConfigurationBuilder.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IWritableJsonConfigurationBuilder -{ - Stream? DefaultFileStream { get; } - - IWritableJsonConfigurationBuilder AddDefaultConfiguration(string Key) where TConfiguration : class; - - IWritableJsonConfigurationBuilder AddDefaultFileStream(Stream stream); - - void Build(string path); -} \ No newline at end of file diff --git a/Framework/Foundation/Configurations/IWritableJsonConfigurationDescriptor.cs b/Framework/Foundation/Configurations/IWritableJsonConfigurationDescriptor.cs deleted file mode 100644 index 15e5eea..0000000 --- a/Framework/Foundation/Configurations/IWritableJsonConfigurationDescriptor.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IWritableJsonConfigurationDescriptor -{ - Type ConfigurationType { get; } - - string Key { get; } -} \ No newline at end of file diff --git a/Framework/Foundation/Configurations/WritableJsonConfigurationBuilder.cs b/Framework/Foundation/Configurations/WritableJsonConfigurationBuilder.cs deleted file mode 100644 index 9dd1c80..0000000 --- a/Framework/Foundation/Configurations/WritableJsonConfigurationBuilder.cs +++ /dev/null @@ -1,105 +0,0 @@ -using Json.Patch; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System.Collections.ObjectModel; -using System.Diagnostics.CodeAnalysis; -using System.Text.Json; -using System.Text.Json.Serialization; -using JsonSerializer = System.Text.Json.JsonSerializer; - -namespace Toolkit.Framework.Foundation; - -public class WritableJsonConfigurationBuilder : IWritableJsonConfigurationBuilder -{ - private readonly List descriptors = new(); - - public Stream? DefaultFileStream { get; private set; } - - public IReadOnlyCollection Descriptors => new ReadOnlyCollection(descriptors); - - public IWritableJsonConfigurationBuilder AddDefaultConfiguration(string Key) where TConfiguration : class - { - descriptors.Add(new WritableJsonConfigurationDescriptor(typeof(TConfiguration), Key)); - return this; - } - - public IWritableJsonConfigurationBuilder AddDefaultFileStream(Stream stream) - { - DefaultFileStream = stream; - return this; - } - - public void Build(string path) - { - JObject? sourceDocument = new(); - if (TryLoadSource(out string? defaultContent)) - { - sourceDocument = JObject.Parse(defaultContent!); - } - - JObject? targetDocument = new(); - if (TryLoadTarget(path, out string? targetContent)) - { - targetDocument = JObject.Parse(targetContent!); - } - - foreach (IWritableJsonConfigurationDescriptor? descriptor in descriptors) - { - if (sourceDocument.SelectToken($"$.{descriptor.Key}") is JToken sourceSection) - { - if (targetDocument.SelectToken($"$.{descriptor.Key}") is JToken targetSection) - { - object? source = JsonSerializer.Deserialize(JsonConvert.SerializeObject(sourceSection), descriptor.ConfigurationType); - object? target = JsonSerializer.Deserialize(JsonConvert.SerializeObject(targetSection), descriptor.ConfigurationType); - - JsonPatch? patch = source.CreatePatch(target); - - object? sourcePatched = patch.Apply(source); - targetSection.Replace(JToken.Parse(JsonSerializer.Serialize(sourcePatched, new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }))); - } - else - { - object? source = JsonSerializer.Deserialize(JsonConvert.SerializeObject(sourceSection), descriptor.ConfigurationType); - targetDocument.Add(descriptor.Key, JToken.Parse(JsonSerializer.Serialize(source, new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }))); - } - } - else - { - object? configuration = Activator.CreateInstance(descriptor.ConfigurationType); - targetDocument.Add(descriptor.Key, JToken.Parse(JsonSerializer.Serialize(configuration, new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }))); - } - } - - using FileStream? fileStream = new(path, FileMode.Create, FileAccess.Write); - using StreamWriter streamWriter = new(fileStream); - using JsonTextWriter writer = new(streamWriter) { Formatting = Formatting.Indented }; - targetDocument.WriteTo(writer); - } - - private bool TryLoadTarget(string path, [MaybeNull] out string? content) - { - if (File.Exists(path)) - { - using FileStream? fileStream = new(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - using StreamReader? streamReader = new(fileStream); - content = streamReader.ReadToEnd(); - return true; - } - - content = null; - return false; - } - - private bool TryLoadSource([MaybeNull] out string? content) - { - if (DefaultFileStream is Stream fileStream) - { - using StreamReader? streamReader = new(fileStream); - content = streamReader.ReadToEnd(); - return true; - } - - content = null; - return false; - } -} \ No newline at end of file diff --git a/Framework/Foundation/Configurations/WritableJsonConfigurationDescriptor.cs b/Framework/Foundation/Configurations/WritableJsonConfigurationDescriptor.cs deleted file mode 100644 index 67f66af..0000000 --- a/Framework/Foundation/Configurations/WritableJsonConfigurationDescriptor.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public record WritableJsonConfigurationDescriptor(Type ConfigurationType, string Key) : IWritableJsonConfigurationDescriptor; \ No newline at end of file diff --git a/Framework/Foundation/Configurations/WritableJsonConfigurationFile.cs b/Framework/Foundation/Configurations/WritableJsonConfigurationFile.cs deleted file mode 100644 index e41886a..0000000 --- a/Framework/Foundation/Configurations/WritableJsonConfigurationFile.cs +++ /dev/null @@ -1,148 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System.Text.Json; - -namespace Toolkit.Framework.Foundation; - -internal class WritableJsonConfigurationFile -{ - private readonly Dictionary data = new(StringComparer.OrdinalIgnoreCase); - private readonly Stack paths = new(); - private JObject tokenCache = new(); - private bool isParsing; - - public IDictionary Parse(Stream input) - { - return ParseStream(input); - } - - public void Write(string key, string value, Stream output) - { - if (isParsing) - { - return; - } - - if (key[^1] == ':') - { - key = key[0..^1]; - } - - string? tokenPath = $"$.{key.Replace(":", ".")}"; - key = key.Replace("[", "").Replace("]", ""); - - if (tokenCache.SelectToken(tokenPath) is JToken token && data.ContainsKey(key)) - { - (JsonValueKind? kind, string _) = data[key]; - object? newValue = ConvertValue(kind, value); - - data[key] = new(kind, value); - token.Replace(JToken.FromObject(newValue)); - } - - using StreamWriter streamWriter = new(output); - using JsonTextWriter writer = new(streamWriter) { Formatting = Formatting.Indented }; - tokenCache.WriteTo(writer); - - output.SetLength(output.Position); - } - - private static object ConvertValue(JsonValueKind? kind, string value) - { - return kind is JsonValueKind.True or JsonValueKind.False ? bool.Parse(value) : value; - } - - private void EnterContext(string context) - { - paths.Push(paths.Count > 0 ? paths.Peek() + ConfigurationPath.KeyDelimiter + context : context); - } - - private void ExitContext() - { - paths.Pop(); - } - - private IDictionary ParseStream(Stream input) - { - data.Clear(); - - JsonDocumentOptions jsonDocumentOptions = new() - { - CommentHandling = JsonCommentHandling.Skip, - AllowTrailingCommas = true, - }; - - isParsing = true; - using (StreamReader? reader = new(input)) - { - string? content = reader.ReadToEnd(); - tokenCache = JObject.Parse(content); - - using JsonDocument? doc = JsonDocument.Parse(content, jsonDocumentOptions); - VisitElement(doc.RootElement); - } - isParsing = false; - - return data.ToDictionary(k => k.Key, v => v.Value.Item2?.ToString() ?? null); - } - - private void VisitElement(JsonElement element) - { - bool isEmpty = true; - - foreach (JsonProperty property in element.EnumerateObject()) - { - isEmpty = false; - - EnterContext(property.Name); - VisitValue(property.Value); - ExitContext(); - } - - if (isEmpty && paths.Count > 0) - { - data[paths.Peek()] = (JsonValueKind.Null, null); - } - } - - private void VisitValue(JsonElement value) - { - switch (value.ValueKind) - { - case JsonValueKind.Object: - VisitElement(value); - break; - - case JsonValueKind.Array: - int index = 0; - foreach (JsonElement arrayElement in value.EnumerateArray()) - { - EnterContext(index.ToString()); - VisitValue(arrayElement); - ExitContext(); - index++; - } - break; - - case JsonValueKind.Number: - case JsonValueKind.String: - case JsonValueKind.True: - case JsonValueKind.False: - case JsonValueKind.Null: - string key = paths.Peek(); - if (data.ContainsKey(key)) - { - throw new FormatException(); - } - data[key] = new(value.ValueKind, value.ToString()); - break; - - case JsonValueKind.Undefined: - break; - - default: - throw new FormatException(); - } - } -} \ No newline at end of file diff --git a/Framework/Foundation/Configurations/WritableJsonConfigurationProvider.cs b/Framework/Foundation/Configurations/WritableJsonConfigurationProvider.cs deleted file mode 100644 index 9ca9f45..0000000 --- a/Framework/Foundation/Configurations/WritableJsonConfigurationProvider.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Microsoft.Extensions.Configuration.Json; -using Microsoft.Extensions.FileProviders; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace Toolkit.Framework.Foundation; - -public class WritableJsonConfigurationProvider : JsonConfigurationProvider, IWritableConfigurationProvider -{ - public WritableJsonConfigurationProvider(JsonConfigurationSource source) : base(source) - { - - } - - public void Write(string section, TValue value) where TValue : class, new() - { - IFileInfo? file = Source.FileProvider?.GetFileInfo(Source.Path ?? string.Empty); - static Stream OpenRead(IFileInfo fileInfo) - { - return fileInfo.PhysicalPath is not null - ? new FileStream(fileInfo.PhysicalPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite) - : fileInfo.CreateReadStream(); - } - - if (file is null) - { - throw new FileNotFoundException(); - } - - using Stream stream = OpenRead(file); - using StreamReader? reader = new(stream); - - string? content = reader.ReadToEnd(); - JObject? document = JObject.Parse(content); - - if (document.SelectToken($"$.{section}") is JToken sectionToken) - { - sectionToken.Replace(JToken.Parse(JsonConvert.SerializeObject(value))); - stream.SetLength(0); - - using StreamWriter streamWriter = new(stream); - using JsonTextWriter writer = new(streamWriter) { Formatting = Formatting.Indented }; - document.WriteTo(writer); - } - } -} \ No newline at end of file diff --git a/Framework/Foundation/Configurations/WritableJsonConfigurationSource.cs b/Framework/Foundation/Configurations/WritableJsonConfigurationSource.cs deleted file mode 100644 index f0a9cc7..0000000 --- a/Framework/Foundation/Configurations/WritableJsonConfigurationSource.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Configuration.Json; -using Microsoft.Extensions.FileProviders; - -namespace Toolkit.Framework.Foundation; - -public class WritableJsonConfigurationSource : JsonConfigurationSource -{ - public IWritableJsonConfigurationBuilder? Factory { get; set; } - - public override IConfigurationProvider Build(IConfigurationBuilder builder) - { - EnsureDefaultsWithSteam(builder); - return new WritableJsonConfigurationProvider(this); - } - - private void EnsureDefaultsWithSteam(IConfigurationBuilder builder) - { - EnsureDefaults(builder); - - if (FileProvider is PhysicalFileProvider physicalFileProvider) - { - string? outputFile = System.IO.Path.Combine(physicalFileProvider.Root, Path!); - Factory?.Build(outputFile); - } - } -} \ No newline at end of file diff --git a/Framework/Foundation/Configurations/Write.cs b/Framework/Foundation/Configurations/Write.cs deleted file mode 100644 index 04d9cb9..0000000 --- a/Framework/Foundation/Configurations/Write.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public record Write(Action UpdateDelegate) : IRequest where TConfiguration : class; \ No newline at end of file diff --git a/Framework/Foundation/Configurations/WriteHandler.cs b/Framework/Foundation/Configurations/WriteHandler.cs deleted file mode 100644 index 7c2bad9..0000000 --- a/Framework/Foundation/Configurations/WriteHandler.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Diagnostics; - -namespace Toolkit.Framework.Foundation; - -public class WriteHandler : IRequestHandler> where TConfiguration : class -{ - private readonly IMediator mediator; - private readonly TConfiguration configuration; - private readonly IConfigurationWriter writer; - - public WriteHandler(TConfiguration configuration, - IConfigurationWriter writer, - IMediator mediator) - { - this.mediator = mediator; - this.configuration = configuration; - this.writer = writer; - } - - public async ValueTask Handle(Write request, CancellationToken cancellationToken) - { - request.UpdateDelegate.Invoke(configuration); - writer.Write(configuration); - - await mediator.Publish(new ConfigurationChanged(configuration), cancellationToken); - - return default; - } -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/Content.cs b/Framework/Foundation/Contents/Content.cs deleted file mode 100644 index b154d06..0000000 --- a/Framework/Foundation/Contents/Content.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public record Content : IRequest -{ - public Content(string name, params object?[] parameters) - { - Name = name; - Parameters = parameters; - } - - public Content(Type type, params object?[] parameters) - { - Type = type; - Parameters = parameters; - } - - public Type? Type { get; } - - public string? Name { get; } - - public object?[] Parameters { get; } -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/ContentTemplateBuilder.cs b/Framework/Foundation/Contents/ContentTemplateBuilder.cs deleted file mode 100644 index 9da3357..0000000 --- a/Framework/Foundation/Contents/ContentTemplateBuilder.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using System.Collections.ObjectModel; - -namespace Toolkit.Framework.Foundation; - -public class ContentTemplateBuilder : IContentTemplateBuilder -{ - private readonly List descriptors = new(); - - public IReadOnlyCollection Descriptors => new ReadOnlyCollection(descriptors); - - public IContentTemplateBuilder Add(string name, ServiceLifetime lifetime = ServiceLifetime.Transient) - { - descriptors.Add(new ContentTemplateDescriptor(typeof(TViewModel), typeof(TView), name, lifetime)); - return this; - } - - public IContentTemplateBuilder Add(ServiceLifetime lifetime = ServiceLifetime.Transient) - { - descriptors.Add(new ContentTemplateDescriptor(typeof(TViewModel), typeof(TView), null, lifetime)); - return this; - } -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/ContentTemplateDescriptor.cs b/Framework/Foundation/Contents/ContentTemplateDescriptor.cs deleted file mode 100644 index 2193d40..0000000 --- a/Framework/Foundation/Contents/ContentTemplateDescriptor.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace Toolkit.Framework.Foundation; - -public class ContentTemplateDescriptor : IContentTemplateDescriptor -{ - public ContentTemplateDescriptor(Type dataType, - Type templateType, - string? name = null, - ServiceLifetime lifetime = ServiceLifetime.Transient) - { - TemplateType = templateType; - ContentType = dataType; - Name = name; - Lifetime = lifetime; - } - - public ServiceLifetime Lifetime { get; } - - public Type TemplateType { get; } - - public Type ContentType { get; } - - public string? Name { get; } -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/ContentTemplateDescriptorProvider.cs b/Framework/Foundation/Contents/ContentTemplateDescriptorProvider.cs deleted file mode 100644 index 1712d3e..0000000 --- a/Framework/Foundation/Contents/ContentTemplateDescriptorProvider.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public class ContentTemplateDescriptorProvider : IContentTemplateDescriptorProvider -{ - private readonly IReadOnlyCollection descriptors; - - public ContentTemplateDescriptorProvider(IReadOnlyCollection descriptors) - { - this.descriptors = descriptors; - } - - public IContentTemplateDescriptor? Get(string name) - { - if (descriptors.FirstOrDefault(x => x.Name == name) is IContentTemplateDescriptor descriptor) - { - return descriptor; - } - - return null; - } - - public IContentTemplateDescriptor? Get(Type type) - { - if (descriptors.FirstOrDefault(x => x.ContentType == type) is IContentTemplateDescriptor descriptor) - { - return descriptor; - } - - return null; - } - - public IContentTemplateDescriptor? Get() - { - if (descriptors.FirstOrDefault(x => x.ContentType == typeof(T)) is IContentTemplateDescriptor descriptor) - { - return descriptor; - } - - return null; - } -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/ContentTemplateFactory.cs b/Framework/Foundation/Contents/ContentTemplateFactory.cs deleted file mode 100644 index 3ac1beb..0000000 --- a/Framework/Foundation/Contents/ContentTemplateFactory.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Diagnostics.CodeAnalysis; - -namespace Toolkit.Framework.Foundation; - -public class ContentTemplateFactory : IContentTemplateFactory -{ - private readonly Dictionary cache = new(); - - private readonly IContentTemplateDescriptorProvider provider; - private readonly IServiceFactory serviceFactory; - - public ContentTemplateFactory(IContentTemplateDescriptorProvider provider, - IServiceFactory serviceFactory) - { - this.provider = provider; - this.serviceFactory = serviceFactory; - } - - public virtual object? Create([MaybeNull] object? data) - { - if (data is null) - { - return null; - } - - if (cache.TryGetValue(data, out object? template)) - { - return template; - } - - if (provider.Get(data.GetType()) is IContentTemplateDescriptor descriptor) - { - template = serviceFactory.Create(descriptor.TemplateType); - if (template is ICache cache) - { - this.cache[data] = cache; - } - } - - return template; - } -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/IContentTemplateBuilder.cs b/Framework/Foundation/Contents/IContentTemplateBuilder.cs deleted file mode 100644 index 0d91dbf..0000000 --- a/Framework/Foundation/Contents/IContentTemplateBuilder.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace Toolkit.Framework.Foundation; - -public interface IContentTemplateBuilder -{ - IReadOnlyCollection Descriptors { get; } - - IContentTemplateBuilder Add(string name, ServiceLifetime lifetime = ServiceLifetime.Transient); - - IContentTemplateBuilder Add(ServiceLifetime lifetime = ServiceLifetime.Transient); -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/IContentTemplateDescriptor.cs b/Framework/Foundation/Contents/IContentTemplateDescriptor.cs deleted file mode 100644 index 5838ea8..0000000 --- a/Framework/Foundation/Contents/IContentTemplateDescriptor.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace Toolkit.Framework.Foundation; - -public interface IContentTemplateDescriptor -{ - Type ContentType { get; } - - ServiceLifetime Lifetime { get; } - - string? Name { get; } - - Type TemplateType { get; } -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/IContentTemplateDescriptorProvider.cs b/Framework/Foundation/Contents/IContentTemplateDescriptorProvider.cs deleted file mode 100644 index 17e882c..0000000 --- a/Framework/Foundation/Contents/IContentTemplateDescriptorProvider.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IContentTemplateDescriptorProvider -{ - IContentTemplateDescriptor? Get(string name); - - IContentTemplateDescriptor? Get(Type type); - - IContentTemplateDescriptor? Get(); -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/IContentTemplateFactory.cs b/Framework/Foundation/Contents/IContentTemplateFactory.cs deleted file mode 100644 index 3d45a87..0000000 --- a/Framework/Foundation/Contents/IContentTemplateFactory.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Diagnostics.CodeAnalysis; - -namespace Toolkit.Framework.Foundation; - -public interface IContentTemplateFactory -{ - object? Create([MaybeNull] object? content); -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/IContentTemplateSelector.cs b/Framework/Foundation/Contents/IContentTemplateSelector.cs deleted file mode 100644 index 72c73b5..0000000 --- a/Framework/Foundation/Contents/IContentTemplateSelector.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IContentTemplateSelector -{ -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/INamedContentFactory.cs b/Framework/Foundation/Contents/INamedContentFactory.cs deleted file mode 100644 index a272818..0000000 --- a/Framework/Foundation/Contents/INamedContentFactory.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface INamedContentTemplateFactory -{ - object? Create(string name); -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/INamedContentTemplateFactory.cs b/Framework/Foundation/Contents/INamedContentTemplateFactory.cs deleted file mode 100644 index 26edeb2..0000000 --- a/Framework/Foundation/Contents/INamedContentTemplateFactory.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface INamedContentFactory -{ - object? Create(string name, params object?[] parameters); -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/ITypedContentFactory.cs b/Framework/Foundation/Contents/ITypedContentFactory.cs deleted file mode 100644 index 6e791db..0000000 --- a/Framework/Foundation/Contents/ITypedContentFactory.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface ITypedContentFactory -{ - object? Create(Type type, params object?[] parameters); -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/NamedContentFactory.cs b/Framework/Foundation/Contents/NamedContentFactory.cs deleted file mode 100644 index 51b0877..0000000 --- a/Framework/Foundation/Contents/NamedContentFactory.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public class NamedContentFactory : INamedContentFactory -{ - private readonly Dictionary cache = new(); - - private readonly IReadOnlyCollection descriptors; - private readonly IServiceFactory serviceFactory; - - public NamedContentFactory(IReadOnlyCollection descriptors, - IServiceFactory serviceFactory) - { - this.descriptors = descriptors; - this.serviceFactory = serviceFactory; - } - - public virtual object? Create(string name, params object?[] parameters) - { - if (cache.TryGetValue(name, out object? data)) - { - return data; - } - - if (descriptors.FirstOrDefault(x => x.Name == name) is IContentTemplateDescriptor descriptor) - { - data = parameters is { Length: > 0 } ? serviceFactory.Create(descriptor.ContentType, parameters) : serviceFactory.Create(descriptor.ContentType); - if (data is ICache cache) - { - this.cache[name] = cache; - } - } - - return data; - } -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/NamedContentTemplateFactory.cs b/Framework/Foundation/Contents/NamedContentTemplateFactory.cs deleted file mode 100644 index d7af3c2..0000000 --- a/Framework/Foundation/Contents/NamedContentTemplateFactory.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public class NamedContentTemplateFactory : INamedContentTemplateFactory -{ - private readonly Dictionary cache = new(); - - private readonly IContentTemplateDescriptorProvider provider; - private readonly IServiceFactory serviceFactory; - - public NamedContentTemplateFactory(IContentTemplateDescriptorProvider provider, - IServiceFactory serviceFactory) - { - this.provider = provider; - this.serviceFactory = serviceFactory; - } - - public virtual object? Create(string name) - { - if (cache.TryGetValue(name, out object? view)) - { - return view; - } - - if (provider.Get(name) is IContentTemplateDescriptor descriptor) - { - view = serviceFactory.Create(descriptor.TemplateType); - if (view is ICache cache) - { - this.cache[name] = cache; - } - - if (descriptor.GetType().GenericTypeArguments is { Length: 2 }) - { - (descriptor as dynamic).ViewInvoker?.Invoke(view); - } - } - - return view; - } -} \ No newline at end of file diff --git a/Framework/Foundation/Contents/TypedContentFactory.cs b/Framework/Foundation/Contents/TypedContentFactory.cs deleted file mode 100644 index 6ed5d19..0000000 --- a/Framework/Foundation/Contents/TypedContentFactory.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public class TypedContentFactory : ITypedContentFactory -{ - private readonly Dictionary cache = new(); - - private readonly IReadOnlyCollection descriptors; - private readonly IServiceFactory serviceFactory; - - public TypedContentFactory(IReadOnlyCollection descriptors, - IServiceFactory serviceFactory) - { - this.descriptors = descriptors; - this.serviceFactory = serviceFactory; - } - - public object? Create(Type type, params object?[] parameters) - { - if (cache.TryGetValue(type, out object? data)) - { - return data; - } - - if (descriptors.FirstOrDefault(x => x.ContentType == type) is IContentTemplateDescriptor descriptor) - { - data = parameters is { Length: > 0 } ? serviceFactory.Create(descriptor.ContentType, parameters) : serviceFactory.Create(descriptor.ContentType); - if (data is ICache cache) - { - this.cache[type] = cache; - } - } - - return data; - } -} \ No newline at end of file diff --git a/Framework/Foundation/Extensions/AssemblyExtensions.cs b/Framework/Foundation/Extensions/AssemblyExtensions.cs deleted file mode 100644 index 05de80a..0000000 --- a/Framework/Foundation/Extensions/AssemblyExtensions.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Reflection; - -namespace Toolkit.Framework.Foundation; - -public static class AssemblyExtensions -{ - public static Stream? ExtractResource(this Assembly assembly, string filename) - { - string? resourceName = $"{assembly.GetName()?.Name?.Replace("-", "_")}.{filename}"; - return assembly.GetManifestResourceStream(resourceName); - } -} diff --git a/Framework/Foundation/Extensions/IServiceCollectionExtensions.cs b/Framework/Foundation/Extensions/IServiceCollectionExtensions.cs deleted file mode 100644 index db6fa0c..0000000 --- a/Framework/Foundation/Extensions/IServiceCollectionExtensions.cs +++ /dev/null @@ -1,127 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; -using System.Diagnostics; - -namespace Toolkit.Framework.Foundation; - -public static class IServiceCollectionExtensions -{ - public static IServiceCollection AddConfiguration(this IServiceCollection serviceCollection, IConfiguration configuration) where TConfiguration : class, new() - { - serviceCollection.Configure(configuration); - serviceCollection.AddTransient(provider => provider.GetService>()!.CurrentValue); - serviceCollection.AddTransient>(); - - return serviceCollection; - } - - public static IServiceCollection AddFoundation(this IServiceCollection serviceCollection) - { - serviceCollection - .AddSingleton() - .AddHandler() - .AddSingleton(provider => new ServiceFactory(provider.GetService, (type, parameters) => ActivatorUtilities.CreateInstance(provider, type, parameters!))) - .AddHandler() - .AddSingleton(provider => new Initialization(() => - { - return serviceCollection.Where(x => x.ServiceType.GetInterfaces() - .Contains(typeof(IInitializable)) || x.ServiceType == typeof(IInitializable)) - .GroupBy(x => x.ServiceType) - .Select(x => x.First()) - .SelectMany(x => provider.GetServices(x.ServiceType) - .Select(x => (IInitializable?)x)).ToList(); - })); - - return serviceCollection; - } - - public static IServiceCollection AddHandler(this IServiceCollection serviceCollection, ServiceLifetime lifetime = ServiceLifetime.Transient) where THandler : notnull - { - if (typeof(THandler).GetInterface(typeof(INotificationHandler<>).Name) is { } notificationContract) - { - if (notificationContract.GetGenericArguments() is { Length: 1 } arguments) - { - Type notificationType = arguments[0]; - - serviceCollection.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), ServiceLifetime.Singleton)); - - serviceCollection.Add(new ServiceDescriptor(typeof(INotificationHandler<>).MakeGenericType(notificationType), sp => sp.GetRequiredService(), lifetime)); - } - } - - if (typeof(THandler).GetInterface(typeof(IRequestHandler<,>).Name) is { } requestContract) - { - if (requestContract.GetGenericArguments() is { Length: 2 } arguments) - { - Type requestType = arguments[0]; - Type responseType = arguments[1]; - - Type wrapperType = typeof(RequestClassHandlerWrapper<,>).MakeGenericType(requestType, responseType); - - serviceCollection.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), lifetime)); - serviceCollection.Add(new ServiceDescriptor(wrapperType, - sp => - { - return sp.GetService()?.Create(wrapperType, sp.GetRequiredService(), sp.GetServices(typeof(IPipelineBehavior<,>).MakeGenericType(requestType, responseType)))!; - }, - lifetime - )); - - } - } - - if (typeof(THandler).GetInterface(typeof(ICommandHandler<,>).Name) is { } commandContract) - { - if (commandContract.GetGenericArguments() is { Length: 2 } arguments) - { - Type requestType = arguments[0]; - Type responseType = arguments[1]; - - Type wrapperType = typeof(CommandClassHandlerWrapper<,>).MakeGenericType(requestType, responseType); - - serviceCollection.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), lifetime)); - serviceCollection.Add(new ServiceDescriptor(wrapperType, - sp => - { - return sp.GetService()?.Create(wrapperType, sp.GetRequiredService(), sp.GetServices(typeof(IPipelineBehavior<,>).MakeGenericType(requestType, responseType)))!; - }, - lifetime - )); - } - } - - if (typeof(THandler).GetInterface(typeof(IQueryHandler<,>).Name) is { } queryContract) - { - if (queryContract.GetGenericArguments() is { Length: 2 } arguments) - { - Type requestType = arguments[0]; - Type responseType = arguments[1]; - - Type wrapperType = typeof(QueryClassHandlerWrapper<,>).MakeGenericType(requestType, responseType); - - serviceCollection.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), lifetime)); - serviceCollection.Add(new ServiceDescriptor(wrapperType, - sp => - { - return sp.GetService()?.Create(wrapperType, sp.GetRequiredService(), sp.GetServices(typeof(IPipelineBehavior<,>).MakeGenericType(requestType, responseType)))!; - }, - lifetime - )); - } - } - return serviceCollection; - } - - public static IServiceCollection AddWritableConfiguration(this IServiceCollection serviceCollection, IConfiguration configuration) where TConfiguration : class, new() - { - serviceCollection.Configure(configuration); - serviceCollection.AddTransient>(provider => provider.GetService()?.Create< ConfigurationWriter>(configuration is IConfigurationSection section ? section.Path : "")!); - serviceCollection.AddTransient(provider => provider.GetService>()!.CurrentValue); - serviceCollection.AddHandler>(); - serviceCollection.AddTransient>(); - - return serviceCollection; - } -} \ No newline at end of file diff --git a/Framework/Foundation/Extensions/IServiceFactoryExtensions.cs b/Framework/Foundation/Extensions/IServiceFactoryExtensions.cs deleted file mode 100644 index 42c455f..0000000 --- a/Framework/Foundation/Extensions/IServiceFactoryExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public static class IServiceFactoryExtensions -{ - public static T? Create(this IServiceFactory serviceFactory, params object?[] parameters) - { - return serviceFactory.Create(typeof(T), parameters); - } - - public static object? Create(this IServiceFactory serviceFactory, Type type) - { - ServiceFactoryDescriptor? descriptor = new(serviceFactory); - return descriptor.Create(type); - } -} \ No newline at end of file diff --git a/Framework/Foundation/Extensions/WritableJsonConfigurationExtensions.cs b/Framework/Foundation/Extensions/WritableJsonConfigurationExtensions.cs deleted file mode 100644 index 8d4011b..0000000 --- a/Framework/Foundation/Extensions/WritableJsonConfigurationExtensions.cs +++ /dev/null @@ -1,75 +0,0 @@ -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.FileProviders; -using Microsoft.Extensions.Hosting; - -namespace Toolkit.Framework.Foundation; - -public static class WritableJsonConfigurationExtensions -{ - public static IConfigurationBuilder AddWritableJsonFile(this IConfigurationBuilder builder, - string path) - { - return builder.AddWritableJsonFile(null, path, false, false, null); - } - - public static IConfigurationBuilder AddWritableJsonFile(this IConfigurationBuilder builder, - string path, - Action? factoryDelegate) - { - return builder.AddWritableJsonFile(null, path, false, false, factoryDelegate); - } - - public static IConfigurationBuilder AddWritableJsonFile(this IConfigurationBuilder builder, - string path, - bool optional) - { - return builder.AddWritableJsonFile(null, path, optional, false, null); - } - - public static IConfigurationBuilder AddWritableJsonFile(this IConfigurationBuilder builder, - string path, - bool optional, - Action? factoryDelegate) - { - return builder.AddWritableJsonFile(null, path, optional, false, factoryDelegate); - } - - public static IConfigurationBuilder AddWritableJsonFile(this IConfigurationBuilder builder, - string path, - bool optional, - bool reloadOnChange) - { - return builder.AddWritableJsonFile( null, path, optional, reloadOnChange, null); - } - - public static IConfigurationBuilder AddWritableJsonFile(this IConfigurationBuilder builder, - string path, - bool optional, - bool reloadOnChange, - Action? factoryDelegate) - { - return builder.AddWritableJsonFile(null, path, optional, reloadOnChange, factoryDelegate); - } - - public static IConfigurationBuilder AddWritableJsonFile(this IConfigurationBuilder builder, - IFileProvider? provider, - string path, - bool optional, - bool reloadOnChange, Action? writableJsonConfigurationDelegate) - { - IWritableJsonConfigurationBuilder writableJsonConfigurationBuilder = new WritableJsonConfigurationBuilder(); - writableJsonConfigurationDelegate?.Invoke(writableJsonConfigurationBuilder); - - return builder.AddWritableJsonFile(configuration => - { - configuration.FileProvider = provider; - configuration.Path = path; - configuration.Optional = optional; - configuration.ReloadOnChange = reloadOnChange; - configuration.Factory = writableJsonConfigurationBuilder; - configuration.ResolveFileProvider(); - }); - } - - public static IConfigurationBuilder AddWritableJsonFile(this IConfigurationBuilder builder, Action configureSource) => builder.Add(configureSource); -} \ No newline at end of file diff --git a/Framework/Foundation/Foundation.csproj b/Framework/Foundation/Foundation.csproj deleted file mode 100644 index 80df8b8..0000000 --- a/Framework/Foundation/Foundation.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - net7.0 - enable - enable - Toolkit.Framework.Foundation - Toolkit.Framework.Foundation - true - - - - - - - - - - - - - diff --git a/Framework/Foundation/Helpers/KeyValueAccumulator.cs b/Framework/Foundation/Helpers/KeyValueAccumulator.cs deleted file mode 100644 index 1c7d8a7..0000000 --- a/Framework/Foundation/Helpers/KeyValueAccumulator.cs +++ /dev/null @@ -1,66 +0,0 @@ -using Microsoft.Extensions.Primitives; - -namespace Toolkit.Framework.Foundation; - -public struct KeyValueAccumulator -{ - private Dictionary accumulator; - private Dictionary> expandingAccumulator; - - public void Append(string key, string value) - { - accumulator ??= new Dictionary(StringComparer.OrdinalIgnoreCase); - - if (accumulator.TryGetValue(key, out StringValues values)) - { - if (values.Count == 0) - { - expandingAccumulator[key].Add(value); - } - else if (values.Count == 1) - { - accumulator[key] = new string[] { values[0]!, value }; - } - else - { - accumulator[key] = default; - - expandingAccumulator ??= new Dictionary>(StringComparer.OrdinalIgnoreCase); - - List list = new(8); - string?[] array = values.ToArray(); - - list.Add(array[0]!); - list.Add(array[1]!); - list.Add(value); - - expandingAccumulator[key] = list; - } - } - else - { - accumulator[key] = new StringValues(value); - } - - ValueCount++; - } - - public bool HasValues => ValueCount > 0; - - public int KeyCount => accumulator?.Count ?? 0; - - public int ValueCount { get; private set; } - - public Dictionary GetResults() - { - if (expandingAccumulator != null) - { - foreach (var entry in expandingAccumulator) - { - accumulator[entry.Key] = new StringValues(entry.Value.ToArray()); - } - } - - return accumulator ?? new Dictionary(0, StringComparer.OrdinalIgnoreCase); - } -} \ No newline at end of file diff --git a/Framework/Foundation/Helpers/QueryHelpers.cs b/Framework/Foundation/Helpers/QueryHelpers.cs deleted file mode 100644 index 7679433..0000000 --- a/Framework/Foundation/Helpers/QueryHelpers.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Microsoft.Extensions.Primitives; -using System.Text; -using System.Text.Encodings.Web; - -namespace Toolkit.Framework.Foundation; - -public static class QueryHelpers -{ - public static Dictionary? ParseNullableQuery(string? queryString) - { - KeyValueAccumulator accumulator = new(); - QueryStringEnumerable enumerable = new(queryString); - - foreach (QueryStringEnumerable.EncodedNameValuePair pair in enumerable) - { - accumulator.Append(pair.DecodeName().ToString(), pair.DecodeValue().ToString()); - } - - if (!accumulator.HasValues) - { - return null; - } - - return accumulator.GetResults(); - } - - public static Dictionary ParseQuery(string? queryString) - { - Dictionary? result = ParseNullableQuery(queryString); - if (result == null) - { - return new Dictionary(); - } - - return result; - } -} \ No newline at end of file diff --git a/Framework/Foundation/Helpers/QueryStringEnumerable.cs b/Framework/Foundation/Helpers/QueryStringEnumerable.cs deleted file mode 100644 index 4c2f4d8..0000000 --- a/Framework/Foundation/Helpers/QueryStringEnumerable.cs +++ /dev/null @@ -1,157 +0,0 @@ -using System.Buffers; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Runtime.Intrinsics; - -readonly struct QueryStringEnumerable -{ - private readonly ReadOnlyMemory queryString; - - public QueryStringEnumerable(string? queryString) : this(queryString.AsMemory()) - { - - } - - public QueryStringEnumerable(ReadOnlyMemory queryString) - { - this.queryString = queryString; - } - - public Enumerator GetEnumerator() => new(queryString); - - public readonly struct EncodedNameValuePair - { - internal EncodedNameValuePair(ReadOnlyMemory encodedName, ReadOnlyMemory encodedValue) - { - EncodedName = encodedName; - EncodedValue = encodedValue; - } - - public readonly ReadOnlyMemory EncodedName { get; } - - public readonly ReadOnlyMemory EncodedValue { get; } - - public ReadOnlyMemory DecodeName() => Decode(EncodedName); - - public ReadOnlyMemory DecodeValue() => Decode(EncodedValue); - - private static ReadOnlyMemory Decode(ReadOnlyMemory chars) - { - return chars.Length < 16 && chars.Span.IndexOfAny('%', '+') < 0 ? chars : Uri.UnescapeDataString(SpanHelper.ReplacePlusWithSpace(chars.Span)).AsMemory(); - } - } - - public struct Enumerator - { - private ReadOnlyMemory query; - - internal Enumerator(ReadOnlyMemory query) - { - Current = default; - this.query = query.IsEmpty || query.Span[0] != '?' ? query : query[1..]; - } - - public EncodedNameValuePair Current { get; private set; } - - public bool MoveNext() - { - while (!query.IsEmpty) - { - ReadOnlyMemory segment; - var delimiterIndex = query.Span.IndexOf('&'); - if (delimiterIndex >= 0) - { - segment = query[..delimiterIndex]; - query = query[(delimiterIndex + 1)..]; - } - else - { - segment = query; - query = default; - } - - int equalIndex = segment.Span.IndexOf('='); - if (equalIndex >= 0) - { - Current = new EncodedNameValuePair(segment[..equalIndex], segment[(equalIndex + 1)..]); - return true; - } - else if (!segment.IsEmpty) - { - Current = new EncodedNameValuePair(segment, default); - return true; - } - } - - Current = default; - return false; - } - } - - private static class SpanHelper - { - private static readonly SpanAction replacePlusWithSpace = ReplacePlusWithSpaceCore; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe string ReplacePlusWithSpace(ReadOnlySpan span) - { - fixed (char* ptr = &MemoryMarshal.GetReference(span)) - { - return string.Create(span.Length, (IntPtr)ptr, replacePlusWithSpace); - } - } - - private static unsafe void ReplacePlusWithSpaceCore(Span buffer, IntPtr state) - { - fixed (char* ptr = &MemoryMarshal.GetReference(buffer)) - { - ushort* input = (ushort*)state.ToPointer(); - ushort* output = (ushort*)ptr; - - nint i = 0; - nint n = (nint)(uint)buffer.Length; - - if (Vector256.IsHardwareAccelerated && n >= Vector256.Count) - { - Vector256 vecPlus = Vector256.Create((ushort)'+'); - Vector256 vecSpace = Vector256.Create((ushort)' '); - - do - { - Vector256 vec = Vector256.Load(input + i); - Vector256 mask = Vector256.Equals(vec, vecPlus); - Vector256 res = Vector256.ConditionalSelect(mask, vecSpace, vec); - res.Store(output + i); - i += Vector256.Count; - } while (i <= n - Vector256.Count); - } - - if (Vector128.IsHardwareAccelerated && n - i >= Vector128.Count) - { - do - { - Vector128 vec = Vector128.Load(input + i); - Vector128 vecPlus = Vector128.Create((ushort)'+'); - Vector128 mask = Vector128.Equals(vec, vecPlus); - Vector128 vecSpace = Vector128.Create((ushort)' '); - Vector128 res = Vector128.ConditionalSelect(mask, vecSpace, vec); - res.Store(output + i); - i += Vector128.Count; - } while (i <= n - Vector128.Count); - } - - for (; i < n; ++i) - { - if (input[i] != '+') - { - output[i] = input[i]; - } - else - { - output[i] = ' '; - } - } - } - } - } -} \ No newline at end of file diff --git a/Framework/Foundation/Lifecycles/AppService.cs b/Framework/Foundation/Lifecycles/AppService.cs deleted file mode 100644 index af5db1b..0000000 --- a/Framework/Foundation/Lifecycles/AppService.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.Extensions.Hosting; - -namespace Toolkit.Framework.Foundation; - -public class AppService : IHostedService -{ - private readonly IMediator mediator; - - public AppService(IMediator mediator) - { - this.mediator = mediator; - } - - public async Task StartAsync(CancellationToken cancellationToken) - { - await mediator.Send(new Initialize()); - await mediator.Send(new Initialized()); - } - - public Task StopAsync(CancellationToken cancellationToken) - { - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/Framework/Foundation/Lifecycles/CommandClassHandlerWrapper.cs b/Framework/Foundation/Lifecycles/CommandClassHandlerWrapper.cs deleted file mode 100644 index 064e5ae..0000000 --- a/Framework/Foundation/Lifecycles/CommandClassHandlerWrapper.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public class CommandClassHandlerWrapper where TRequest : class, ICommand -{ - private readonly MessageHandlerDelegate handler; - - public CommandClassHandlerWrapper(ICommandHandler concreteHandler, - IEnumerable> pipelineBehaviours) - { - MessageHandlerDelegate handler = concreteHandler.Handle; - - foreach (IPipelineBehavior? pipeline in pipelineBehaviours.Reverse()) - { - MessageHandlerDelegate handlerCopy = handler; - IPipelineBehavior pipelineCopy = pipeline; - handler = (TRequest message, CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy); - } - - this.handler = handler; - } - - public ValueTask Handle(TRequest request, CancellationToken cancellationToken) => handler(request, cancellationToken); -} diff --git a/Framework/Foundation/Lifecycles/Disposer.cs b/Framework/Foundation/Lifecycles/Disposer.cs deleted file mode 100644 index 1b1731e..0000000 --- a/Framework/Foundation/Lifecycles/Disposer.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Runtime.CompilerServices; -using System.Reactive.Disposables; - -namespace Toolkit.Framework.Foundation; - -public class Disposer : IDisposer -{ - private readonly ConditionalWeakTable subjects = new(); - - public void Add(object subject, params object[] objects) - { - CompositeDisposable disposables = subjects.GetOrCreateValue(subject); - foreach (IDisposable disposable in objects.OfType()) - { - disposables.Add(disposable); - } - } - - public TDisposable Replace(object subject, IDisposable disposer, TDisposable replacement) where TDisposable : IDisposable - { - CompositeDisposable disposables = subjects.GetOrCreateValue(subject); - if (disposer is not null) - { - disposables.Remove(disposer); - } - - disposables.Add(replacement); - return replacement; - } - public void Remove(object subject, IDisposable disposer) - { - CompositeDisposable disposables = subjects.GetOrCreateValue(subject); - if (disposer is not null) - { - disposables.Remove(disposer); - } - } - - public void Dispose(object subject) - { - if (subjects.TryGetValue(subject, out CompositeDisposable disposables)) - { - disposables.Dispose(); - } - } -} diff --git a/Framework/Foundation/Lifecycles/ICache.cs b/Framework/Foundation/Lifecycles/ICache.cs deleted file mode 100644 index ad44126..0000000 --- a/Framework/Foundation/Lifecycles/ICache.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface ICache -{ -} \ No newline at end of file diff --git a/Framework/Foundation/Lifecycles/ICommand.cs b/Framework/Foundation/Lifecycles/ICommand.cs deleted file mode 100644 index 7a93b34..0000000 --- a/Framework/Foundation/Lifecycles/ICommand.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface ICommand : IMessage { } -public interface ICommand : ICommand { } diff --git a/Framework/Foundation/Lifecycles/ICommandHandler.cs b/Framework/Foundation/Lifecycles/ICommandHandler.cs deleted file mode 100644 index 167dc24..0000000 --- a/Framework/Foundation/Lifecycles/ICommandHandler.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface ICommandHandler : ICommandHandler where TCommand : ICommand { } - -public interface ICommandHandler where TCommand : ICommand -{ - ValueTask Handle(TCommand command, CancellationToken cancellationToken); -} diff --git a/Framework/Foundation/Lifecycles/IDisposer.cs b/Framework/Foundation/Lifecycles/IDisposer.cs deleted file mode 100644 index 74226cd..0000000 --- a/Framework/Foundation/Lifecycles/IDisposer.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IDisposer -{ - void Add(object subject, params object[] objects); - - void Remove(object subject, IDisposable disposer); - - void Dispose(object subject); -} diff --git a/Framework/Foundation/Lifecycles/IInitializable.cs b/Framework/Foundation/Lifecycles/IInitializable.cs deleted file mode 100644 index 909a2c2..0000000 --- a/Framework/Foundation/Lifecycles/IInitializable.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IInitializable -{ - Task InitializeAsync(); -} \ No newline at end of file diff --git a/Framework/Foundation/Lifecycles/IInitialization.cs b/Framework/Foundation/Lifecycles/IInitialization.cs deleted file mode 100644 index 392fcdf..0000000 --- a/Framework/Foundation/Lifecycles/IInitialization.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IInitialization -{ - Task InitializeAsync(); -} \ No newline at end of file diff --git a/Framework/Foundation/Lifecycles/IMediator.cs b/Framework/Foundation/Lifecycles/IMediator.cs deleted file mode 100644 index e0b768c..0000000 --- a/Framework/Foundation/Lifecycles/IMediator.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IMediator -{ - ValueTask Publish(TNotification notification, CancellationToken cancellationToken = default) where TNotification : INotification; - - ValueTask Send(IRequest request, CancellationToken cancellationToken = default); - - ValueTask Send(ICommand command, CancellationToken cancellationToken = default); - - ValueTask Send(IQuery query, CancellationToken cancellationToken = default); - - ValueTask Send(object message, CancellationToken cancellationToken = default); - - void Subscribe(object subscriber); -} diff --git a/Framework/Foundation/Lifecycles/IMessage.cs b/Framework/Foundation/Lifecycles/IMessage.cs deleted file mode 100644 index 66decab..0000000 --- a/Framework/Foundation/Lifecycles/IMessage.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IMessage { } diff --git a/Framework/Foundation/Lifecycles/INotification.cs b/Framework/Foundation/Lifecycles/INotification.cs deleted file mode 100644 index 838acf5..0000000 --- a/Framework/Foundation/Lifecycles/INotification.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface INotification : IMessage { } diff --git a/Framework/Foundation/Lifecycles/INotificationHandler.cs b/Framework/Foundation/Lifecycles/INotificationHandler.cs deleted file mode 100644 index b99fae7..0000000 --- a/Framework/Foundation/Lifecycles/INotificationHandler.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface INotificationHandler where TNotification : INotification -{ - ValueTask Handle(TNotification notification, CancellationToken cancellationToken); -} diff --git a/Framework/Foundation/Lifecycles/IPipelineBehavior.cs b/Framework/Foundation/Lifecycles/IPipelineBehavior.cs deleted file mode 100644 index 00f7f7f..0000000 --- a/Framework/Foundation/Lifecycles/IPipelineBehavior.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IPipelineBehavior where TMessage : notnull, IMessage -{ - ValueTask Handle( - TMessage message, - CancellationToken cancellationToken, - MessageHandlerDelegate next - ); -} diff --git a/Framework/Foundation/Lifecycles/IQuery.cs b/Framework/Foundation/Lifecycles/IQuery.cs deleted file mode 100644 index b351070..0000000 --- a/Framework/Foundation/Lifecycles/IQuery.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IQuery : IMessage { } diff --git a/Framework/Foundation/Lifecycles/IQueryHandler.cs b/Framework/Foundation/Lifecycles/IQueryHandler.cs deleted file mode 100644 index 208db43..0000000 --- a/Framework/Foundation/Lifecycles/IQueryHandler.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IQueryHandler where TQuery : IQuery -{ - ValueTask Handle(TQuery query, CancellationToken cancellationToken); -} diff --git a/Framework/Foundation/Lifecycles/IRequest.cs b/Framework/Foundation/Lifecycles/IRequest.cs deleted file mode 100644 index 6940a47..0000000 --- a/Framework/Foundation/Lifecycles/IRequest.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IRequest : IRequest { } - -public interface IRequest : IMessage { } diff --git a/Framework/Foundation/Lifecycles/IRequestHandler.cs b/Framework/Foundation/Lifecycles/IRequestHandler.cs deleted file mode 100644 index 737d1d8..0000000 --- a/Framework/Foundation/Lifecycles/IRequestHandler.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IRequestHandler : IRequestHandler where TRequest : IRequest -{ - -} - -public interface IRequestHandler where TRequest : IRequest -{ - ValueTask Handle(TRequest request, CancellationToken cancellationToken); -} \ No newline at end of file diff --git a/Framework/Foundation/Lifecycles/Initialization.cs b/Framework/Foundation/Lifecycles/Initialization.cs deleted file mode 100644 index 35bca79..0000000 --- a/Framework/Foundation/Lifecycles/Initialization.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public class Initialization : IInitialization -{ - private readonly Func> factory; - - public Initialization(Func> factory) - { - this.factory = factory; - } - - public async Task InitializeAsync() - { - foreach (IInitializable? initializer in factory()) - { - if (initializer is not null) - { - await initializer.InitializeAsync(); - } - } - } -} \ No newline at end of file diff --git a/Framework/Foundation/Lifecycles/Initialize.cs b/Framework/Foundation/Lifecycles/Initialize.cs deleted file mode 100644 index 107d7c9..0000000 --- a/Framework/Foundation/Lifecycles/Initialize.cs +++ /dev/null @@ -1,4 +0,0 @@ - -namespace Toolkit.Framework.Foundation; - -public record Initialize : IRequest; \ No newline at end of file diff --git a/Framework/Foundation/Lifecycles/InitializeHandler.cs b/Framework/Foundation/Lifecycles/InitializeHandler.cs deleted file mode 100644 index a35b75b..0000000 --- a/Framework/Foundation/Lifecycles/InitializeHandler.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public class InitializeHandler : IRequestHandler -{ - private readonly IInitialization initialization; - - public InitializeHandler(IInitialization initialization) - { - this.initialization = initialization; - } - - public async ValueTask Handle(Initialize request, CancellationToken cancellationToken) - { - await initialization.InitializeAsync(); - return default; - } -} \ No newline at end of file diff --git a/Framework/Foundation/Lifecycles/Initialized.cs b/Framework/Foundation/Lifecycles/Initialized.cs deleted file mode 100644 index 8205908..0000000 --- a/Framework/Foundation/Lifecycles/Initialized.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public record class Initialized : IRequest; \ No newline at end of file diff --git a/Framework/Foundation/Lifecycles/Mediator.cs b/Framework/Foundation/Lifecycles/Mediator.cs deleted file mode 100644 index 5e79e62..0000000 --- a/Framework/Foundation/Lifecycles/Mediator.cs +++ /dev/null @@ -1,136 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using System.Runtime.CompilerServices; - -namespace Toolkit.Framework.Foundation; - -public class Mediator : IMediator -{ - private readonly IServiceProvider factory; - - private readonly ConditionalWeakTable handlers = new(); - - public Mediator(IServiceProvider factory) - { - this.factory = factory; - } - - public ValueTask Publish(TNotification notification, CancellationToken cancellationToken = default) where TNotification : INotification - { - List> handlers = factory.GetServices>().ToList(); - - foreach (KeyValuePair handler in this.handlers) - { - if (handler.Key == typeof(TNotification)) - { - handlers.Add(handler.Value); - } - } - - if (handlers.Count == 0) - { - return default; - } - else if (handlers.Count == 1) - { - return handlers[0].Handle(notification, cancellationToken); - } - - return default; - } - - public ValueTask Send(IRequest request, CancellationToken cancellationToken = default) - { - dynamic? handler = factory.GetService(typeof(RequestClassHandlerWrapper<,>).MakeGenericType(request.GetType(), typeof(TResponse))); - if (handler is not null) - { - return handler.Handle((dynamic)request, cancellationToken); - } - - return default; - } - - public ValueTask Send(ICommand command, CancellationToken cancellationToken = default) - { - dynamic? handler = factory.GetService(typeof(CommandClassHandlerWrapper<,>).MakeGenericType(command.GetType(), typeof(TResponse))); - if (handler is not null) - { - return handler.Handle((dynamic)command, cancellationToken); - } - - return default; - } - - public ValueTask Send(IQuery query, CancellationToken cancellationToken = default) - { - dynamic? handler = factory.GetService(typeof(QueryClassHandlerWrapper<,>).MakeGenericType(query.GetType(), typeof(TResponse))); - if (handler is not null) - { - return handler.Handle((dynamic)query, cancellationToken); - } - - return default; - } - - public ValueTask Send(object message, CancellationToken cancellationToken = default) - { - if (message.GetType().GetInterface(typeof(IRequest<>).Name) is { } requestType) - { - if (requestType.GetGenericArguments() is { Length: 1 } arguments) - { - Type responseType = arguments[0]; - - dynamic? handler = factory.GetService(typeof(RequestClassHandlerWrapper<,>).MakeGenericType(message.GetType(), responseType)); - if (handler is not null) - { - return handler.Handle((dynamic)message, cancellationToken); - } - } - } - - if (message.GetType().GetInterface(typeof(ICommand<>).Name) is { } commandType) - { - if (commandType.GetGenericArguments() is { Length: 1 } arguments) - { - Type responseType = arguments[0]; - - dynamic? handler = factory.GetService(typeof(CommandClassHandlerWrapper<,>).MakeGenericType(message.GetType(), responseType)); - if (handler is not null) - { - return handler.Handle((dynamic)message, cancellationToken); - } - } - } - - if (message.GetType().GetInterface(typeof(IQuery<>).Name) is { } queryType) - { - if (queryType.GetGenericArguments() is { Length: 1 } arguments) - { - Type responseType = arguments[0]; - - dynamic? handler = factory.GetService(typeof(QueryClassHandlerWrapper<,>).MakeGenericType(message.GetType(), responseType)); - if (handler is not null) - { - return handler.Handle((dynamic)message, cancellationToken); - } - } - } - - return default; - } - - public void Subscribe(object subject) - { - Type[] interfaceTypes = subject.GetType().GetInterfaces(); - foreach (Type interfaceType in interfaceTypes.Where(x => x.IsGenericType)) - { - if (interfaceType.GetGenericTypeDefinition() == typeof(INotificationHandler<>)) - { - if (interfaceType.GetGenericArguments() is { Length: 1 } arguments) - { - Type notificationType = arguments[0]; - handlers.Add(notificationType, subject); - } - } - } - } -} diff --git a/Framework/Foundation/Lifecycles/MessageHandlerDelegate.cs b/Framework/Foundation/Lifecycles/MessageHandlerDelegate.cs deleted file mode 100644 index f4a5c8d..0000000 --- a/Framework/Foundation/Lifecycles/MessageHandlerDelegate.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public delegate ValueTask MessageHandlerDelegate(TMessage message, CancellationToken cancellationToken) where TMessage : notnull, IMessage; diff --git a/Framework/Foundation/Lifecycles/QueryClassHandlerWrapper.cs b/Framework/Foundation/Lifecycles/QueryClassHandlerWrapper.cs deleted file mode 100644 index 033b8cf..0000000 --- a/Framework/Foundation/Lifecycles/QueryClassHandlerWrapper.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public class QueryClassHandlerWrapper where TRequest : class, IQuery -{ - private readonly MessageHandlerDelegate handler; - - public QueryClassHandlerWrapper(IQueryHandler concreteHandler, - IEnumerable> pipelineBehaviours) - { - MessageHandlerDelegate handler = concreteHandler.Handle; - - foreach (IPipelineBehavior? pipeline in pipelineBehaviours.Reverse()) - { - MessageHandlerDelegate handlerCopy = handler; - IPipelineBehavior pipelineCopy = pipeline; - handler = (TRequest message, CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy); - } - - this.handler = handler; - } - - public ValueTask Handle(TRequest request, CancellationToken cancellationToken) => - handler(request, cancellationToken); -} diff --git a/Framework/Foundation/Lifecycles/RequestClassHandlerWrapper.cs b/Framework/Foundation/Lifecycles/RequestClassHandlerWrapper.cs deleted file mode 100644 index cbcd98c..0000000 --- a/Framework/Foundation/Lifecycles/RequestClassHandlerWrapper.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public class RequestClassHandlerWrapper where TRequest : class, IRequest -{ - private readonly MessageHandlerDelegate handler; - - public RequestClassHandlerWrapper(IRequestHandler concreteHandler, - IEnumerable> pipelineBehaviours) - { - MessageHandlerDelegate handler = concreteHandler.Handle; - foreach (IPipelineBehavior? pipeline in pipelineBehaviours.Reverse()) - { - MessageHandlerDelegate handlerCopy = handler; - IPipelineBehavior pipelineCopy = pipeline; - - handler = (TRequest message, CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy); - } - - this.handler = handler; - } - - public ValueTask Handle(TRequest request, CancellationToken cancellationToken) => handler(request, cancellationToken); -} \ No newline at end of file diff --git a/Framework/Foundation/Navigation/IEventParameter.cs b/Framework/Foundation/Navigation/IEventParameter.cs deleted file mode 100644 index 9c7eaa1..0000000 --- a/Framework/Foundation/Navigation/IEventParameter.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IEventParameter -{ - List GetValues(EventArgs args); -} \ No newline at end of file diff --git a/Framework/Foundation/Navigation/INavigationConfirmation.cs b/Framework/Foundation/Navigation/INavigationConfirmation.cs deleted file mode 100644 index eb53fca..0000000 --- a/Framework/Foundation/Navigation/INavigationConfirmation.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface INavigationConfirmation -{ - ValueTask CanConfirm(); -} - -public interface INavigated -{ - ValueTask Navigated(); -} \ No newline at end of file diff --git a/Framework/Foundation/Navigation/INavigationRouteDescriptor.cs b/Framework/Foundation/Navigation/INavigationRouteDescriptor.cs deleted file mode 100644 index 46f40ad..0000000 --- a/Framework/Foundation/Navigation/INavigationRouteDescriptor.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface INavigationRouteDescriptor -{ - object Route { get; } - - string? Name { get; } -} \ No newline at end of file diff --git a/Framework/Foundation/Navigation/INavigationRouteDescriptorCollection.cs b/Framework/Foundation/Navigation/INavigationRouteDescriptorCollection.cs deleted file mode 100644 index 223feb9..0000000 --- a/Framework/Foundation/Navigation/INavigationRouteDescriptorCollection.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface INavigationRouteDescriptorCollection : IList -{ -} \ No newline at end of file diff --git a/Framework/Foundation/Navigation/IParameter.cs b/Framework/Foundation/Navigation/IParameter.cs deleted file mode 100644 index 1e876a9..0000000 --- a/Framework/Foundation/Navigation/IParameter.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IParameter -{ - string? Key { get; } - - KeyValuePair? GetValue(object target); -} \ No newline at end of file diff --git a/Framework/Foundation/Navigation/Navigate.cs b/Framework/Foundation/Navigation/Navigate.cs deleted file mode 100644 index 2d4eaef..0000000 --- a/Framework/Foundation/Navigation/Navigate.cs +++ /dev/null @@ -1,15 +0,0 @@ - -namespace Toolkit.Framework.Foundation; - -public record Navigate : IRequest -{ - public Navigate(string path, params object?[] parameters) - { - Path = path; - Parameters = parameters; - } - - public string? Path { get; } - - public object?[] Parameters { get; } -} \ No newline at end of file diff --git a/Framework/Foundation/Navigation/NavigateBack.cs b/Framework/Foundation/Navigation/NavigateBack.cs deleted file mode 100644 index 93712e2..0000000 --- a/Framework/Foundation/Navigation/NavigateBack.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public record NavigateBack(object Route) : IRequest; \ No newline at end of file diff --git a/Framework/Foundation/Navigation/NavigationRoute.cs b/Framework/Foundation/Navigation/NavigationRoute.cs deleted file mode 100644 index d27d350..0000000 --- a/Framework/Foundation/Navigation/NavigationRoute.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public record NavigationRoute(string Name, object Route) : IRequest; \ No newline at end of file diff --git a/Framework/Foundation/Navigation/NavigationRouteDescriptor.cs b/Framework/Foundation/Navigation/NavigationRouteDescriptor.cs deleted file mode 100644 index 87dbcf1..0000000 --- a/Framework/Foundation/Navigation/NavigationRouteDescriptor.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public record NavigationRouteDescriptor : INavigationRouteDescriptor -{ - public NavigationRouteDescriptor(string name, object route) - { - Name = name; - Route = route; - } - - public string Name { get; } - - public object Route { get; } -} \ No newline at end of file diff --git a/Framework/Foundation/Navigation/NavigationRouteDescriptorCollection.cs b/Framework/Foundation/Navigation/NavigationRouteDescriptorCollection.cs deleted file mode 100644 index 28db78e..0000000 --- a/Framework/Foundation/Navigation/NavigationRouteDescriptorCollection.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public class NavigationRouteDescriptorCollection : List, INavigationRouteDescriptorCollection -{ - public NavigationRouteDescriptorCollection(IEnumerable collection) : base(collection) - { - } -} \ No newline at end of file diff --git a/Framework/Foundation/Navigation/NavigationSegment.cs b/Framework/Foundation/Navigation/NavigationSegment.cs deleted file mode 100644 index 47a13ca..0000000 --- a/Framework/Foundation/Navigation/NavigationSegment.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Microsoft.Extensions.Primitives; -using System.Diagnostics; - -namespace Toolkit.Framework.Foundation; - -public class NavigationSegment -{ - private NavigationSegment(string name, IDictionary parameters, string target) - { - Name = name; - Parameters = parameters; - Target = target; - } - - public string Name { get; } - - public IDictionary Parameters { get; } - - public string Target { get; } - - public static IReadOnlyCollection FromPath(string? path) - { - List result = new(); - - if (path is null) - { - return result; - } - - string[] pathParts = path.Split('?'); - - string[] segments = pathParts is { Length: >= 1 } ? pathParts[0].Split('/', StringSplitOptions.RemoveEmptyEntries) - : Array.Empty(); - string query = pathParts is { Length: 2 } ? pathParts[1] : ""; - - Dictionary parameters = QueryHelpers.ParseQuery(query); - - foreach (string segment in segments) - { - string[] segmentParts = segment.Split('#'); - - string name = segmentParts is { Length: >= 1 } ? segmentParts[0] : ""; - string target = segmentParts is { Length: 2 } ? segmentParts[1] : ""; - - Trace.WriteLine(name); - Trace.WriteLine(target); - - result.Add(new NavigationSegment(name, parameters, target)); - } - - return result; - } -} diff --git a/Framework/Foundation/Services/Create.cs b/Framework/Foundation/Services/Create.cs deleted file mode 100644 index 494707f..0000000 --- a/Framework/Foundation/Services/Create.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public record Create(Type Type, params object?[] Parameters) : IRequest; diff --git a/Framework/Foundation/Services/IServiceCreator.cs b/Framework/Foundation/Services/IServiceCreator.cs deleted file mode 100644 index 86d5ec8..0000000 --- a/Framework/Foundation/Services/IServiceCreator.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IServiceCreator -{ - object Create(Func creator, params object[] parameters); -} \ No newline at end of file diff --git a/Framework/Foundation/Services/IServiceFactory.cs b/Framework/Foundation/Services/IServiceFactory.cs deleted file mode 100644 index 6b0ec62..0000000 --- a/Framework/Foundation/Services/IServiceFactory.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public interface IServiceFactory -{ - object? Create(Type type, params object?[] parameters); - - T? Create(Type type, params object?[] parameters); -} \ No newline at end of file diff --git a/Framework/Foundation/Services/ServiceCreator.cs b/Framework/Foundation/Services/ServiceCreator.cs deleted file mode 100644 index 69aff32..0000000 --- a/Framework/Foundation/Services/ServiceCreator.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public class ServiceCreator : IServiceCreator -{ - public object Create(Func creator, params object[] parameters) - { - return creator(typeof(T), parameters); - } -} \ No newline at end of file diff --git a/Framework/Foundation/Services/ServiceFactory.cs b/Framework/Foundation/Services/ServiceFactory.cs deleted file mode 100644 index 62c747d..0000000 --- a/Framework/Foundation/Services/ServiceFactory.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public class ServiceFactory : IServiceFactory -{ - private readonly Func factory; - private readonly Func creator; - - public ServiceFactory(Func factory, Func creator) - { - this.factory = factory; - this.creator = creator; - } - - public object? Create(Type type, params object?[] parameters) - { - dynamic? lookup = factory(typeof(IServiceCreator<>).MakeGenericType(type)); - return lookup is not null ? lookup.Create(creator, parameters) : creator(type, parameters); - } - - public T? Create(Type type, params object?[] parameters) - { - dynamic? lookup = factory(typeof(IServiceCreator<>).MakeGenericType(type)); - return lookup is not null ? (T)lookup.Create(creator, parameters) : (T)creator(type, parameters); - } -} \ No newline at end of file diff --git a/Framework/Foundation/Services/ServiceFactoryDescriptor.cs b/Framework/Foundation/Services/ServiceFactoryDescriptor.cs deleted file mode 100644 index 9f0ac58..0000000 --- a/Framework/Foundation/Services/ServiceFactoryDescriptor.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Reflection; - -namespace Toolkit.Framework.Foundation; - -internal class ServiceFactoryDescriptor -{ - private readonly IServiceFactory serviceFactory; - - public ServiceFactoryDescriptor(IServiceFactory serviceFactory) - { - this.serviceFactory = serviceFactory; - } - - public object? Create(Type type) - { - MethodInfo? methodInfo = typeof(ServiceFactoryDescriptor).GetMethod(nameof(Create), BindingFlags.NonPublic | BindingFlags.Instance); - return methodInfo?.MakeGenericMethod(type).Invoke(this, new object[] { type }); - } - - private T? Create(Type type) - { - return serviceFactory.Create(type); - } -} \ No newline at end of file diff --git a/Framework/Foundation/Services/ServiceFactoryHandler.cs b/Framework/Foundation/Services/ServiceFactoryHandler.cs deleted file mode 100644 index 13460ff..0000000 --- a/Framework/Foundation/Services/ServiceFactoryHandler.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Toolkit.Framework.Foundation; - -public class ServiceFactoryHandler : IRequestHandler -{ - private readonly IServiceFactory factory; - - public ServiceFactoryHandler(IServiceFactory factory) - { - this.factory = factory; - } - public async ValueTask Handle(Create request, CancellationToken cancellationToken) - { - return await Task.FromResult(factory.Create(request.Type, request.Parameters)); - } -} diff --git a/Toolkit.Foundation/AppService.cs b/Toolkit.Foundation/AppService.cs new file mode 100644 index 0000000..c318344 --- /dev/null +++ b/Toolkit.Foundation/AppService.cs @@ -0,0 +1,20 @@ +using Microsoft.Extensions.Hosting; + +namespace Toolkit.Foundation; + +public class AppService(IEnumerable initializers, + IPublisher publisher) : + IHostedService +{ + public async Task StartAsync(CancellationToken cancellationToken) + { + foreach (IInitializer initializer in initializers) + { + await initializer.Initialize(); + } + + await publisher.Publish(cancellationToken); + } + + public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; +} \ No newline at end of file diff --git a/Toolkit.Foundation/AsyncLock.cs b/Toolkit.Foundation/AsyncLock.cs new file mode 100644 index 0000000..56dc549 --- /dev/null +++ b/Toolkit.Foundation/AsyncLock.cs @@ -0,0 +1,23 @@ +using System.Runtime.CompilerServices; + +namespace Toolkit.Foundation; + +public class AsyncLock(int initial = 1, + int maximum = 1) : + IDisposable +{ + private readonly SemaphoreSlim semaphore = new(initial, maximum); + + public void Dispose() + { + semaphore.Release(); + } + + public TaskAwaiter GetAwaiter() => LockAsync().GetAwaiter(); + + private async Task LockAsync() + { + await semaphore.WaitAsync(); + return this; + } +} diff --git a/Toolkit.Foundation/Cache.cs b/Toolkit.Foundation/Cache.cs new file mode 100644 index 0000000..a5c0cfd --- /dev/null +++ b/Toolkit.Foundation/Cache.cs @@ -0,0 +1,68 @@ +using HyperX; +using System.Collections; +using System.Collections.Concurrent; +using System.Reactive.Disposables; + +namespace Toolkit.Foundation; + +public class Cache(IDisposer disposer) : + ICache +{ + private readonly List cache = []; + + public void Add(TValue value) + { + if (value is null) + { + return; + } + + disposer.Add(value, Disposable.Create(() => Remove(value))); + cache.Add(value); + } + + public void Clear() => cache.Clear(); + + public IEnumerator GetEnumerator() => cache.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public bool Remove(TValue value) => cache.Remove(value); +} + +public class Cache : + ICache + where TKey : + notnull + where TValue : + notnull +{ + private readonly ConcurrentDictionary cache = new(); + + public void Add(TKey key, + TValue value) + { + cache.TryAdd(key, value); + } + + public void Clear() => cache.Clear(); + + public bool ContainsKey(TKey key) => cache.ContainsKey(key); + + public IEnumerator> GetEnumerator() => cache.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public bool Remove(TKey key) => cache.Remove(key, out _); + + public bool TryGetValue(TKey key, out TValue? value) + { + if (cache.TryGetValue(key, out value)) + { + return true; + } + + value = default; + return false; + } +} \ No newline at end of file diff --git a/Toolkit.Foundation/Changed.cs b/Toolkit.Foundation/Changed.cs new file mode 100644 index 0000000..82fd0df --- /dev/null +++ b/Toolkit.Foundation/Changed.cs @@ -0,0 +1,3 @@ +namespace Toolkit.Foundation; + +public record Changed(TValue? Value = default) : INotification; \ No newline at end of file diff --git a/Toolkit.Foundation/CommandValueViewModel.cs b/Toolkit.Foundation/CommandValueViewModel.cs new file mode 100644 index 0000000..f2b7717 --- /dev/null +++ b/Toolkit.Foundation/CommandValueViewModel.cs @@ -0,0 +1,17 @@ +using CommunityToolkit.Mvvm.Input; + +namespace Toolkit.Foundation; + +public partial class CommandValueViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer) : + ValueViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer) +{ + public IRelayCommand InvokeCommand => + new AsyncRelayCommand(InvokeAsync); + + protected virtual Task InvokeAsync() => + Task.CompletedTask; +} \ No newline at end of file diff --git a/Toolkit.Foundation/CommandViewModel.cs b/Toolkit.Foundation/CommandViewModel.cs new file mode 100644 index 0000000..740f078 --- /dev/null +++ b/Toolkit.Foundation/CommandViewModel.cs @@ -0,0 +1,17 @@ +using CommunityToolkit.Mvvm.Input; + +namespace Toolkit.Foundation; + +public partial class CommandViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer) : + ObservableViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer) +{ + public IRelayCommand InvokeCommand => + new AsyncRelayCommand(InvokeAsync); + + protected virtual Task InvokeAsync() => + Task.CompletedTask; +} \ No newline at end of file diff --git a/Toolkit.Foundation/ComponentBuilder.cs b/Toolkit.Foundation/ComponentBuilder.cs new file mode 100644 index 0000000..eef2252 --- /dev/null +++ b/Toolkit.Foundation/ComponentBuilder.cs @@ -0,0 +1,91 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Toolkit.Foundation; + +public class ComponentBuilder : + IComponentBuilder +{ + private readonly IHostBuilder hostBuilder; + + private bool configurationRegistered; + + private ComponentBuilder() + { + hostBuilder = new HostBuilder() + .UseContentRoot("Local", true) + .ConfigureAppConfiguration(config => + { + config.AddJsonFile("Settings.json", true, true); + }) + .ConfigureServices((context, services) => + { + services.AddScoped(); + + services.AddScoped(provider => + new ServiceFactory((type, parameters) => + ActivatorUtilities.CreateInstance(provider, type, parameters!))); + + services.AddScoped(); + services.AddScoped(); + + services.AddTransient(); + services.AddTransient(); + + services.AddTransient(); + services.AddScoped(); + + services.AddTransient(); + + services.AddTransient(); + services.AddScoped(); + services.AddTransient(); + + services.AddHandler(); + services.AddHandler(); + }); + } + + public static IComponentBuilder Create() => + new ComponentBuilder(); + + public IComponentBuilder AddConfiguration(Action configurationDelegate) + where TConfiguration : ComponentConfiguration, new() + { + if (configurationRegistered) + { + return this; + } + + configurationRegistered = true; + TConfiguration configuration = new(); + + if (configurationDelegate is not null) + { + configurationDelegate(configuration); + } + + hostBuilder.ConfigureServices(services => + { + services.AddConfiguration(section: configuration.GetType().Name, + configuration: configuration); + + services.AddConfiguration(configuration); + }); + + return this; + } + + public IComponentHost Build() + { + IHost host = hostBuilder.Build(); + return host.Services.GetRequiredService(); + } + + public IComponentBuilder AddServices(Action configureDelegate) + { + hostBuilder.ConfigureServices(configureDelegate); + return this; + } +} \ No newline at end of file diff --git a/Toolkit.Foundation/ComponentConfiguration.cs b/Toolkit.Foundation/ComponentConfiguration.cs new file mode 100644 index 0000000..72feb26 --- /dev/null +++ b/Toolkit.Foundation/ComponentConfiguration.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; + +namespace Toolkit.Foundation; + +public record ComponentConfiguration +{ + public string? Description { get; set; } + + public string? Name { get; set; } + + [JsonInclude] + internal Guid Id { get; set; } = Guid.NewGuid(); +} \ No newline at end of file diff --git a/Toolkit.Foundation/ComponentConfigurationViewModel.cs b/Toolkit.Foundation/ComponentConfigurationViewModel.cs new file mode 100644 index 0000000..4eafe1e --- /dev/null +++ b/Toolkit.Foundation/ComponentConfigurationViewModel.cs @@ -0,0 +1,111 @@ +using CommunityToolkit.Mvvm.ComponentModel; + +namespace Toolkit.Foundation; + +public partial class ComponentConfigurationViewModel : + ValueViewModel, + IComponentConfigurationViewModel, + INotificationHandler> + where TConfiguration : class +{ + public ComponentConfigurationViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer, + THeader header, + TDescription description, + TAction action) : base(serviceProvider, serviceFactory, publisher, subscriber, disposer) + { + + } + + public Task Handle(Changed args, + CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } +} + +public partial class ComponentConfigurationViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer, + TAction action, + TConfiguration configuration, + Func valueDelegate, + object header, + object description) : + ValueViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer), + IComponentConfigurationViewModel, + INotificationHandler> + where TConfiguration : class +{ + [ObservableProperty] + private TAction action = action; + + [ObservableProperty] + private object header = header; + + [ObservableProperty] + private object description = description; + + public override Task Activated() + { + Value = valueDelegate.Invoke(configuration); + return base.Activated(); + } + public Task Handle(Changed args, + CancellationToken cancellationToken = default) + { + if (args.Value is TConfiguration configuration) + { + Value = valueDelegate.Invoke(configuration); + } + + return Task.CompletedTask; + } +} + +public partial class ComponentConfigurationViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer, + TAction action, + TDescription description, + TConfiguration configuration, + Func valueDelegate, + object header) : + ValueViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer), + IComponentConfigurationViewModel, + INotificationHandler> + where TConfiguration : class +{ + [ObservableProperty] + private TAction action = action; + + [ObservableProperty] + private object header = header; + + [ObservableProperty] + private TDescription description = description; + + public override Task Activated() + { + Value = valueDelegate.Invoke(configuration); + return base.Activated(); + } + + public Task Handle(Changed args, + CancellationToken cancellationToken = default) + { + if (args.Value is TConfiguration configuration) + { + Value = valueDelegate.Invoke(configuration); + } + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/Toolkit.Foundation/ComponentHost.cs b/Toolkit.Foundation/ComponentHost.cs new file mode 100644 index 0000000..f660820 --- /dev/null +++ b/Toolkit.Foundation/ComponentHost.cs @@ -0,0 +1,41 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Toolkit.Foundation; + +public sealed class ComponentHost(IServiceProvider services, + IEnumerable initializers, + IEnumerable hostedServices) : + IComponentHost +{ + public IServiceProvider Services => services; + + public ComponentConfiguration? Configuration => + Services.GetService(); + + public void Dispose() + { + + } + + public async Task StartAsync(CancellationToken cancellationToken = default) + { + foreach (IInitializer initializer in initializers) + { + await initializer.Initialize(); + } + + foreach (IHostedService service in hostedServices) + { + await service.StartAsync(cancellationToken); + } + } + + public async Task StopAsync(CancellationToken cancellationToken = default) + { + foreach (IHostedService service in hostedServices) + { + await service.StopAsync(cancellationToken); + } + } +} diff --git a/Toolkit.Foundation/ComponentHostCollection.cs b/Toolkit.Foundation/ComponentHostCollection.cs new file mode 100644 index 0000000..c55e2d7 --- /dev/null +++ b/Toolkit.Foundation/ComponentHostCollection.cs @@ -0,0 +1,21 @@ +using System.Collections; + +namespace Toolkit.Foundation; + +public class ComponentHostCollection : + IComponentHostCollection + +{ + private readonly List hosts = []; + + public void Add(IComponentHost host) + { + hosts.Add(host); + } + + public IEnumerator GetEnumerator() => + hosts.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => + hosts.GetEnumerator(); +} diff --git a/Toolkit.Foundation/ComponentInitializer.cs b/Toolkit.Foundation/ComponentInitializer.cs new file mode 100644 index 0000000..a758541 --- /dev/null +++ b/Toolkit.Foundation/ComponentInitializer.cs @@ -0,0 +1,49 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Toolkit.Foundation; + +public class ComponentInitializer(IEnumerable components, + IProxyServiceCollection typedServices, + IComponentHostCollection hosts, + IComponentScopeCollection scopes, + IServiceProvider provider) : + IInitializer +{ + public async Task Initialize() + { + foreach (IComponent component in components) + { + 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(typedServices.Services); + }); + + IComponentHost host = builder.Build(); + + scopes.Add(component.GetType().Name, + host.Services.GetRequiredService()); + + hosts.Add(host); + await host.StartAsync(); + } + } +} diff --git a/Toolkit.Foundation/ComponentScopeCollection.cs b/Toolkit.Foundation/ComponentScopeCollection.cs new file mode 100644 index 0000000..d944e5d --- /dev/null +++ b/Toolkit.Foundation/ComponentScopeCollection.cs @@ -0,0 +1,4 @@ +namespace Toolkit.Foundation; + +public class ComponentScopeCollection : Dictionary, + IComponentScopeCollection; diff --git a/Toolkit.Foundation/ComponentScopeProvider.cs b/Toolkit.Foundation/ComponentScopeProvider.cs new file mode 100644 index 0000000..f0b28f4 --- /dev/null +++ b/Toolkit.Foundation/ComponentScopeProvider.cs @@ -0,0 +1,12 @@ +namespace Toolkit.Foundation; + +public class ComponentScopeProvider(IComponentScopeCollection scopes) : + IComponentScopeProvider +{ + public IServiceProvider? Get(string name) + { + return scopes.TryGetValue(name, + out IServiceProvider? scope) ? scope : default; + } +} + diff --git a/Toolkit.Foundation/Configuration.cs b/Toolkit.Foundation/Configuration.cs new file mode 100644 index 0000000..f577181 --- /dev/null +++ b/Toolkit.Foundation/Configuration.cs @@ -0,0 +1,9 @@ +namespace Toolkit.Foundation; + +public class Configuration(IConfigurationReader reader) : + IConfiguration + where TConfiguration : + class +{ + public TConfiguration Value => reader.Read(); +} diff --git a/Toolkit.Foundation/ConfigurationChangedHandler.cs b/Toolkit.Foundation/ConfigurationChangedHandler.cs new file mode 100644 index 0000000..de6d8cf --- /dev/null +++ b/Toolkit.Foundation/ConfigurationChangedHandler.cs @@ -0,0 +1,21 @@ +namespace Toolkit.Foundation; + +public class ConfigurationChangedHandler(ConfigurationValue configurationValue) : + INotificationHandler> + where TValue : + class, new() +{ + public Task Handle(Changed args, + CancellationToken cancellationToken = default) + { + if (args.Value is TConfiguration configuration) + { + if (configurationValue.TryUpdate(configuration, out TValue value)) + { + + } + } + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/Toolkit.Foundation/ConfigurationFactory.cs b/Toolkit.Foundation/ConfigurationFactory.cs new file mode 100644 index 0000000..d41debd --- /dev/null +++ b/Toolkit.Foundation/ConfigurationFactory.cs @@ -0,0 +1,9 @@ +namespace Toolkit.Foundation; + +public class ConfigurationFactory(Func factory) : + IConfigurationFactory + where TConfiguration : + class +{ + public object Create() => factory.Invoke(); +} diff --git a/Toolkit.Foundation/ConfigurationFile.cs b/Toolkit.Foundation/ConfigurationFile.cs new file mode 100644 index 0000000..50fcd4c --- /dev/null +++ b/Toolkit.Foundation/ConfigurationFile.cs @@ -0,0 +1,11 @@ +using Microsoft.Extensions.FileProviders; + +namespace Toolkit.Foundation; + +public class ConfigurationFile(IFileInfo fileInfo) : + IConfigurationFile + where TConfiguration : + class +{ + public IFileInfo FileInfo => fileInfo; +} diff --git a/Toolkit.Foundation/ConfigurationInitializer.cs b/Toolkit.Foundation/ConfigurationInitializer.cs new file mode 100644 index 0000000..29977cb --- /dev/null +++ b/Toolkit.Foundation/ConfigurationInitializer.cs @@ -0,0 +1,25 @@ +namespace Toolkit.Foundation; + +public class ConfigurationInitializer(IPublisher publisher, + IConfigurationReader reader, + IConfigurationWriter writer, + IConfigurationFactory factory) : + IConfigurationInitializer, + IInitializer + where TConfiguration : + class +{ + public async Task Initialize() + { + if (!reader.TryRead(out TConfiguration? configuration)) + { + if (factory.Create() is object defaultConfiguration) + { + configuration = (TConfiguration?)defaultConfiguration; + writer.Write(defaultConfiguration); + } + } + + await publisher.PublishUI(new Changed(configuration)); + } +} diff --git a/Toolkit.Foundation/ConfigurationMonitor.cs b/Toolkit.Foundation/ConfigurationMonitor.cs new file mode 100644 index 0000000..cfe6228 --- /dev/null +++ b/Toolkit.Foundation/ConfigurationMonitor.cs @@ -0,0 +1,46 @@ +namespace Toolkit.Foundation; + +public class ConfigurationMonitor(IConfigurationFile file, + IConfigurationReader reader, + IPublisher publisher) : + IConfigurationMonitor + where TConfiguration : + class +{ + private FileSystemWatcher? watcher; + + public Task StartAsync(CancellationToken cancellationToken) + { + async void ChangedHandler(object sender, + FileSystemEventArgs args) + { + if (reader.Read() is { } configuration) + { + await publisher.PublishUI(new Changed(configuration)); + } + } + + if (file.FileInfo.PhysicalPath is { } path) + { + string fileName = Path.GetFileName(path); + + watcher = new FileSystemWatcher + { + NotifyFilter = NotifyFilters.LastWrite, + Path = path.Replace(fileName, ""), + Filter = fileName, + EnableRaisingEvents = true + }; + + watcher.Changed += ChangedHandler; + } + + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + watcher?.Dispose(); + return Task.CompletedTask; + } +} diff --git a/Toolkit.Foundation/ConfigurationReader.cs b/Toolkit.Foundation/ConfigurationReader.cs new file mode 100644 index 0000000..098f45c --- /dev/null +++ b/Toolkit.Foundation/ConfigurationReader.cs @@ -0,0 +1,33 @@ +namespace Toolkit.Foundation; + +public class ConfigurationReader(IConfigurationSource source, + IConfigurationFactory factory) : + IConfigurationReader + where TConfiguration : + class +{ + public TConfiguration Read() + { + if (source.TryGet(out TConfiguration? value)) + { + if (value is TConfiguration configuration) + { + return configuration; + } + } + + return (TConfiguration)factory.Create(); + } + + public bool TryRead(out TConfiguration? configuration) + { + if (source.TryGet(out TConfiguration? value) && value is not null) + { + configuration = value; + return true; + } + + configuration = default; + return false; + } +} diff --git a/Toolkit.Foundation/ConfigurationSource.cs b/Toolkit.Foundation/ConfigurationSource.cs new file mode 100644 index 0000000..8484f2b --- /dev/null +++ b/Toolkit.Foundation/ConfigurationSource.cs @@ -0,0 +1,132 @@ +using Microsoft.Extensions.FileProviders; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Toolkit.Foundation; + +public class ConfigurationSource(IConfigurationFile configurationFile, + string section, + JsonSerializerOptions? serializerOptions = null) : + IConfigurationSource + where TConfiguration : + class +{ + private readonly object lockingObject = new(); + + private static readonly Func defaultSerializerOptions = new(() => + { + return new JsonSerializerOptions + { + WriteIndented = true, + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + Converters = + { + new JsonStringEnumConverter(), + new DictionaryStringObjectJsonConverter() + } + }; + }); + + public void Set(TConfiguration value) => Set((object)value); + + public void Set(object value) + { + lock (lockingObject) + { + IFileInfo fileInfo = configurationFile.FileInfo; + + if (!File.Exists(fileInfo.PhysicalPath)) + { + string? fileDirectoryPath = Path.GetDirectoryName(fileInfo.PhysicalPath); + if (!string.IsNullOrEmpty(fileDirectoryPath)) + { + Directory.CreateDirectory(fileDirectoryPath); + } + + File.WriteAllText(fileInfo.PhysicalPath!, "{}"); + } + + static Stream OpenReadWrite(IFileInfo fileInfo) + { + return fileInfo.PhysicalPath is not null + ? new FileStream(fileInfo.PhysicalPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite) + : fileInfo.CreateReadStream(); + } + + using Stream stream = OpenReadWrite(fileInfo); + using StreamReader? reader = new(stream); + + string? content = reader.ReadToEnd(); + using JsonDocument jsonDocument = JsonDocument.Parse(content); + + using Stream stream2 = OpenReadWrite(fileInfo); + Utf8JsonWriter writer = new(stream2, new JsonWriterOptions() + { + Indented = true, + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + }); + + writer.WriteStartObject(); + bool isWritten = false; + + JsonDocument optionsElement = JsonDocument.Parse(JsonSerializer.SerializeToUtf8Bytes(value, + serializerOptions ?? defaultSerializerOptions())); + + foreach (JsonProperty element in jsonDocument.RootElement.EnumerateObject()) + { + if (element.Name != section) + { + element.WriteTo(writer); + continue; + } + writer.WritePropertyName(element.Name); + optionsElement.WriteTo(writer); + isWritten = true; + } + + if (!isWritten) + { + writer.WritePropertyName(section); + optionsElement.WriteTo(writer); + } + + writer.WriteEndObject(); + writer.Flush(); + stream2.SetLength(stream2.Position); + } + } + + public bool TryGet(out TConfiguration? value) + { + lock (lockingObject) + { + IFileInfo fileInfo = configurationFile.FileInfo; + + if (File.Exists(fileInfo.PhysicalPath)) + { + static Stream OpenRead(IFileInfo fileInfo) + { + return fileInfo.PhysicalPath is not null + ? new FileStream(fileInfo.PhysicalPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite) + : fileInfo.CreateReadStream(); + } + + using Stream stream = OpenRead(fileInfo); + using StreamReader? reader = new(stream); + + string? content = reader.ReadToEnd(); + + using JsonDocument jsonDocument = JsonDocument.Parse(content); + if (jsonDocument.RootElement.TryGetProperty(section, out JsonElement sectionValue)) + { + value = JsonSerializer.Deserialize(sectionValue.ToString(), serializerOptions ?? defaultSerializerOptions()); + return true; + } + } + + value = default; + return false; + } + } +} \ No newline at end of file diff --git a/Toolkit.Foundation/ConfigurationValue.cs b/Toolkit.Foundation/ConfigurationValue.cs new file mode 100644 index 0000000..4efe3ab --- /dev/null +++ b/Toolkit.Foundation/ConfigurationValue.cs @@ -0,0 +1,25 @@ +namespace Toolkit.Foundation; + +public class ConfigurationValue(Func> changed) + where TValue : + class, new() +{ + private TValue? currentValue; + + public bool TryUpdate(TConfiguration configuration, + out TValue value) + { + TValue newValue = new(); + changed(configuration).Invoke(newValue); + + if (!EqualityComparer.Default.Equals(currentValue, newValue)) + { + value = newValue; + currentValue = newValue; + return true; + } + + value = currentValue!; + return false; + } +} \ No newline at end of file diff --git a/Toolkit.Foundation/ConfigurationWriter.cs b/Toolkit.Foundation/ConfigurationWriter.cs new file mode 100644 index 0000000..41544be --- /dev/null +++ b/Toolkit.Foundation/ConfigurationWriter.cs @@ -0,0 +1,23 @@ +namespace Toolkit.Foundation; + +public class ConfigurationWriter(IConfigurationSource source) : + IConfigurationWriter + where TConfiguration : + class +{ + public void Write(Action updateDelegate) + { + if (source.TryGet(out TConfiguration? value)) + { + if (value is not null) + { + updateDelegate?.Invoke(value); + Write(value); + } + } + } + + public void Write(object value) => source.Set(value); + + public void Write(TConfiguration value) => source.Set(value); +} \ No newline at end of file diff --git a/Toolkit.Foundation/ContentTemplateDescriptor.cs b/Toolkit.Foundation/ContentTemplateDescriptor.cs new file mode 100644 index 0000000..427d71e --- /dev/null +++ b/Toolkit.Foundation/ContentTemplateDescriptor.cs @@ -0,0 +1,16 @@ +namespace Toolkit.Foundation; + +public class ContentTemplateDescriptor(object key, + Type viewModelType, + Type viewType, + params object[]? parameters) : + IContentTemplateDescriptor +{ + public object Key => key; + + public object[]? Parameters => parameters; + + public Type ContentType => viewModelType; + + public Type TemplateType => viewType; +} \ No newline at end of file diff --git a/Toolkit.Foundation/ContentTemplateDescriptorProvider.cs b/Toolkit.Foundation/ContentTemplateDescriptorProvider.cs new file mode 100644 index 0000000..a4f1404 --- /dev/null +++ b/Toolkit.Foundation/ContentTemplateDescriptorProvider.cs @@ -0,0 +1,18 @@ +using System.Xml.Linq; + +namespace Toolkit.Foundation; + +public class ContentTemplateDescriptorProvider(IEnumerable contentTemplates) : + IContentTemplateDescriptorProvider +{ + public IContentTemplateDescriptor? Get(object key) + { + if (contentTemplates.FirstOrDefault(x => x.Key.Equals(key) || x.Key.Equals($"{key}".Replace("ViewModel", ""))) + is IContentTemplateDescriptor viewModelTemplate) + { + return viewModelTemplate; + } + + return default; + } +} diff --git a/Toolkit.Foundation/Create.cs b/Toolkit.Foundation/Create.cs new file mode 100644 index 0000000..9483a29 --- /dev/null +++ b/Toolkit.Foundation/Create.cs @@ -0,0 +1,5 @@ + +namespace Toolkit.Foundation; + +public record Create(TValue Value) : + INotification; \ No newline at end of file diff --git a/Toolkit.Foundation/DefaultBuilder.cs b/Toolkit.Foundation/DefaultBuilder.cs new file mode 100644 index 0000000..1a2474b --- /dev/null +++ b/Toolkit.Foundation/DefaultBuilder.cs @@ -0,0 +1,68 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Toolkit.Foundation; + +namespace Toolkit.Foundation; + +public class DefaultBuilder : + HostBuilder +{ + public static IHostBuilder Create() + { + return new HostBuilder() + .UseContentRoot("Local", true) + .ConfigureAppConfiguration(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.AddScoped(provider => new ComponentScopeCollection + { + { "Default", provider.GetRequiredService() } + }); + + services.AddTransient(); + + services.AddHandler(); + services.AddHandler(); + + services.AddInitializer(); + services.AddHostedService(); + }); + } +} diff --git a/Toolkit.Foundation/DictionaryStringObjectJsonConverter.cs b/Toolkit.Foundation/DictionaryStringObjectJsonConverter.cs new file mode 100644 index 0000000..595fb6e --- /dev/null +++ b/Toolkit.Foundation/DictionaryStringObjectJsonConverter.cs @@ -0,0 +1,84 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Toolkit.Foundation; + +public class DictionaryStringObjectJsonConverter : + JsonConverter> +{ + public override bool CanConvert(Type typeToConvert) => + typeToConvert == typeof(Dictionary) || + typeToConvert == typeof(Dictionary); + + public override Dictionary Read(ref Utf8JsonReader reader, + Type typeToConvert, + JsonSerializerOptions options) + { + Dictionary dictionary = []; + + if (reader.TokenType == JsonTokenType.StartObject) + { + while (reader.Read()) + { + if (reader.TokenType == JsonTokenType.EndObject) + { + return dictionary; + } + + if (reader.TokenType is JsonTokenType.PropertyName) + { + string? propertyName = reader.GetString(); + if (!string.IsNullOrWhiteSpace(propertyName)) + { + reader.Read(); + dictionary.Add(propertyName!, ExtractValue(ref reader, options)); + } + } + } + } + + return dictionary; + } + + public override void Write(Utf8JsonWriter writer, + Dictionary value, + JsonSerializerOptions options) => + JsonSerializer.Serialize(writer, (IDictionary)value, options); + + private object? ExtractValue(ref Utf8JsonReader reader, + JsonSerializerOptions options) + { + switch (reader.TokenType) + { + case JsonTokenType.String: + if (reader.TryGetDateTime(out var date)) + { + return date; + } + return reader.GetString(); + case JsonTokenType.False: + return false; + case JsonTokenType.True: + return true; + case JsonTokenType.Null: + return null; + case JsonTokenType.Number: + if (reader.TryGetInt64(out var result)) + { + return result; + } + return reader.GetDecimal(); + case JsonTokenType.StartObject: + return Read(ref reader, null!, options); + case JsonTokenType.StartArray: + List list = []; + while (reader.Read() && reader.TokenType != JsonTokenType.EndArray) + { + list.Add(ExtractValue(ref reader, options)); + } + return list; + default: + return default; + } + } +} \ No newline at end of file diff --git a/Toolkit.Foundation/Disposer.cs b/Toolkit.Foundation/Disposer.cs new file mode 100644 index 0000000..093120c --- /dev/null +++ b/Toolkit.Foundation/Disposer.cs @@ -0,0 +1,81 @@ +using System.Reactive.Disposables; +using System.Collections; +using System.Collections.Concurrent; + +namespace Toolkit.Foundation; + +public class Disposer : + IDisposer +{ + private readonly ConcurrentDictionary subjects = []; + + public void Add(object subject, + params object[] objects) + { + CompositeDisposable disposables = subjects.GetOrAdd(subject, args => new CompositeDisposable()); + foreach (IDisposable disposable in objects.OfType()) + { + disposables.Add(disposable); + } + + foreach (object notDisposable in objects.Where(x => x is not IDisposable)) + { + disposables.Add(Disposable.Create(() => FromNotDisposable(notDisposable))); + } + } + + private void FromNotDisposable(object target) + { + if (target is IList collection && collection is { Count: > 0 }) + { + foreach (object? item in collection) + { + FromNotDisposable(item); + } + } + + if (target is IDisposable disposable) + { + disposable.Dispose(); + } + + if (target is not IDisposable) + { + Dispose(target); + } + } + + public TDisposable Replace(object subject, + IDisposable disposer, + TDisposable replacement) + where TDisposable : + IDisposable + { + CompositeDisposable disposables = subjects.GetOrAdd(subject, args => new CompositeDisposable()); + if (disposer is not null) + { + disposables.Remove(disposer); + } + + disposables.Add(replacement); + return replacement; + } + + public void Remove(object subject, + IDisposable disposer) + { + CompositeDisposable disposables = subjects.GetOrAdd(subject, args => new CompositeDisposable()); + if (disposer is not null) + { + disposables.Remove(disposer); + } + } + + public void Dispose(object subject) + { + if (subjects.TryGetValue(subject, out CompositeDisposable? disposables)) + { + disposables?.Dispose(); + } + } +} diff --git a/Toolkit.Foundation/Enumerate.cs b/Toolkit.Foundation/Enumerate.cs new file mode 100644 index 0000000..14d385f --- /dev/null +++ b/Toolkit.Foundation/Enumerate.cs @@ -0,0 +1,3 @@ +namespace Toolkit.Foundation; + +public record Enumerate(object? Key = null) : INotification; \ No newline at end of file diff --git a/Toolkit.Foundation/HandlerDelegate.cs b/Toolkit.Foundation/HandlerDelegate.cs new file mode 100644 index 0000000..73ce94b --- /dev/null +++ b/Toolkit.Foundation/HandlerDelegate.cs @@ -0,0 +1,5 @@ +namespace Toolkit.Foundation; + +public delegate Task HandlerDelegate(TMessage message, + CancellationToken cancellationToken) + where TMessage : IMessage; \ No newline at end of file diff --git a/Toolkit.Foundation/HandlerWrapper.cs b/Toolkit.Foundation/HandlerWrapper.cs new file mode 100644 index 0000000..f5ba764 --- /dev/null +++ b/Toolkit.Foundation/HandlerWrapper.cs @@ -0,0 +1,25 @@ +namespace Toolkit.Foundation; + +public class HandlerWrapper(IHandler handler, + IEnumerable> pipelineBehaviours) + where TMessage : class, IRequest +{ + private readonly IEnumerable> pipelineBehaviours = + pipelineBehaviours.Reverse(); + + public async Task Handle(TMessage message, + CancellationToken cancellationToken) + { + HandlerDelegate currentHandler = handler.Handle; + foreach (IPipelineBehavior behavior in pipelineBehaviours) + { + HandlerDelegate previousHandler = currentHandler; + currentHandler = async (args, token) => + { + return await behavior.Handle(args, previousHandler, token); + }; + } + + return await currentHandler(message, cancellationToken); + } +} \ No newline at end of file diff --git a/Toolkit.Foundation/IActivated.cs b/Toolkit.Foundation/IActivated.cs new file mode 100644 index 0000000..224ec70 --- /dev/null +++ b/Toolkit.Foundation/IActivated.cs @@ -0,0 +1,11 @@ +namespace Toolkit.Foundation; + +public interface IActivated +{ + Task Activated(); +} + +public interface IActivated +{ + Task Activated(TResult result); +} \ No newline at end of file diff --git a/Toolkit.Foundation/ICache.cs b/Toolkit.Foundation/ICache.cs new file mode 100644 index 0000000..de9420c --- /dev/null +++ b/Toolkit.Foundation/ICache.cs @@ -0,0 +1,30 @@ +namespace Toolkit.Foundation; + +public interface ICache : + IEnumerable +{ + void Add(TValue value); + + void Clear(); + + bool Remove(TValue value); +} + +public interface ICache : + IEnumerable> + where TKey : + notnull + where TValue : + notnull +{ + void Add(TKey key, + TValue value); + + void Clear(); + + bool ContainsKey(TKey key); + + bool Remove(TKey key); + + bool TryGetValue(TKey key, out TValue? value); +} diff --git a/Toolkit.Foundation/IComponent.cs b/Toolkit.Foundation/IComponent.cs new file mode 100644 index 0000000..9165c0f --- /dev/null +++ b/Toolkit.Foundation/IComponent.cs @@ -0,0 +1,6 @@ +namespace Toolkit.Foundation; + +public interface IComponent +{ + IComponentBuilder Create(); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IComponentBuilder.cs b/Toolkit.Foundation/IComponentBuilder.cs new file mode 100644 index 0000000..d65586e --- /dev/null +++ b/Toolkit.Foundation/IComponentBuilder.cs @@ -0,0 +1,13 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Toolkit.Foundation; + +public interface IComponentBuilder +{ + IComponentBuilder AddConfiguration(Action configurationDelegate) + where TConfiguration : ComponentConfiguration, new(); + + IComponentHost Build(); + + IComponentBuilder AddServices(Action configureDelegate); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IComponentConfigurationViewModel.cs b/Toolkit.Foundation/IComponentConfigurationViewModel.cs new file mode 100644 index 0000000..f7eb4cd --- /dev/null +++ b/Toolkit.Foundation/IComponentConfigurationViewModel.cs @@ -0,0 +1,6 @@ +namespace Toolkit.Foundation; + +public interface IComponentConfigurationViewModel +{ + +} diff --git a/Toolkit.Foundation/IComponentHost.cs b/Toolkit.Foundation/IComponentHost.cs new file mode 100644 index 0000000..3990386 --- /dev/null +++ b/Toolkit.Foundation/IComponentHost.cs @@ -0,0 +1,9 @@ +using Microsoft.Extensions.Hosting; + +namespace Toolkit.Foundation; + +public interface IComponentHost : + IHost +{ + ComponentConfiguration? Configuration { get; } +} \ No newline at end of file diff --git a/Toolkit.Foundation/IComponentHostCollection.cs b/Toolkit.Foundation/IComponentHostCollection.cs new file mode 100644 index 0000000..141a0cc --- /dev/null +++ b/Toolkit.Foundation/IComponentHostCollection.cs @@ -0,0 +1,7 @@ +namespace Toolkit.Foundation; + +public interface IComponentHostCollection : + IEnumerable +{ + void Add(IComponentHost host); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IComponentScopeCollection.cs b/Toolkit.Foundation/IComponentScopeCollection.cs new file mode 100644 index 0000000..72eb836 --- /dev/null +++ b/Toolkit.Foundation/IComponentScopeCollection.cs @@ -0,0 +1,5 @@ +namespace Toolkit.Foundation; + +public interface IComponentScopeCollection : + IDictionary; + diff --git a/Toolkit.Foundation/IComponentScopeProvider.cs b/Toolkit.Foundation/IComponentScopeProvider.cs new file mode 100644 index 0000000..bf5cfc2 --- /dev/null +++ b/Toolkit.Foundation/IComponentScopeProvider.cs @@ -0,0 +1,7 @@ +namespace Toolkit.Foundation; + +public interface IComponentScopeProvider +{ + IServiceProvider? Get(string name); +} + diff --git a/Toolkit.Foundation/IConfiguration.cs b/Toolkit.Foundation/IConfiguration.cs new file mode 100644 index 0000000..cf4ef25 --- /dev/null +++ b/Toolkit.Foundation/IConfiguration.cs @@ -0,0 +1,8 @@ +namespace Toolkit.Foundation; + +public interface IConfiguration + where TConfiguration : + class +{ + TConfiguration Value { get; } +} diff --git a/Toolkit.Foundation/IConfigurationChanged.cs b/Toolkit.Foundation/IConfigurationChanged.cs new file mode 100644 index 0000000..f00fe22 --- /dev/null +++ b/Toolkit.Foundation/IConfigurationChanged.cs @@ -0,0 +1,4 @@ +namespace Toolkit.Foundation; + +public interface IConfigurationChanged : + IInitializer; \ No newline at end of file diff --git a/Toolkit.Foundation/IConfigurationFactory.cs b/Toolkit.Foundation/IConfigurationFactory.cs new file mode 100644 index 0000000..916812a --- /dev/null +++ b/Toolkit.Foundation/IConfigurationFactory.cs @@ -0,0 +1,8 @@ +namespace Toolkit.Foundation; + +public interface IConfigurationFactory + where TConfiguration : + class +{ + object Create(); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IConfigurationFile.cs b/Toolkit.Foundation/IConfigurationFile.cs new file mode 100644 index 0000000..baec244 --- /dev/null +++ b/Toolkit.Foundation/IConfigurationFile.cs @@ -0,0 +1,10 @@ +using Microsoft.Extensions.FileProviders; + +namespace Toolkit.Foundation; + +public interface IConfigurationFile + where TConfiguration : + class +{ + IFileInfo FileInfo { get; } +} diff --git a/Toolkit.Foundation/IConfigurationInitializer.cs b/Toolkit.Foundation/IConfigurationInitializer.cs new file mode 100644 index 0000000..597609f --- /dev/null +++ b/Toolkit.Foundation/IConfigurationInitializer.cs @@ -0,0 +1,8 @@ +namespace Toolkit.Foundation; + +public interface IConfigurationInitializer + where TConfiguration : + class +{ + Task Initialize(); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IConfigurationMonitor.cs b/Toolkit.Foundation/IConfigurationMonitor.cs new file mode 100644 index 0000000..3a18e99 --- /dev/null +++ b/Toolkit.Foundation/IConfigurationMonitor.cs @@ -0,0 +1,9 @@ + +using Microsoft.Extensions.Hosting; + +namespace Toolkit.Foundation; + +public interface IConfigurationMonitor : + IHostedService + where TConfiguration : + class; \ No newline at end of file diff --git a/Toolkit.Foundation/IConfigurationReader.cs b/Toolkit.Foundation/IConfigurationReader.cs new file mode 100644 index 0000000..7e2f5e5 --- /dev/null +++ b/Toolkit.Foundation/IConfigurationReader.cs @@ -0,0 +1,10 @@ +namespace Toolkit.Foundation; + +public interface IConfigurationReader + where TConfiguration : + class +{ + bool TryRead(out TConfiguration? configuration); + + TConfiguration Read(); +} diff --git a/Toolkit.Foundation/IConfigurationSource.cs b/Toolkit.Foundation/IConfigurationSource.cs new file mode 100644 index 0000000..626e754 --- /dev/null +++ b/Toolkit.Foundation/IConfigurationSource.cs @@ -0,0 +1,12 @@ +namespace Toolkit.Foundation; + +public interface IConfigurationSource + where TConfiguration : + class +{ + bool TryGet(out TConfiguration? value); + + void Set(TConfiguration value); + + void Set(object value); +} diff --git a/Toolkit.Foundation/IConfigurationWriter.cs b/Toolkit.Foundation/IConfigurationWriter.cs new file mode 100644 index 0000000..388723b --- /dev/null +++ b/Toolkit.Foundation/IConfigurationWriter.cs @@ -0,0 +1,12 @@ +namespace Toolkit.Foundation; + +public interface IConfigurationWriter + where TConfiguration : + class +{ + void Write(Action updateDelegate); + + void Write(object value); + + void Write(TConfiguration value); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IContentTemplate.cs b/Toolkit.Foundation/IContentTemplate.cs new file mode 100644 index 0000000..6eb73fb --- /dev/null +++ b/Toolkit.Foundation/IContentTemplate.cs @@ -0,0 +1,6 @@ +namespace Toolkit.Foundation; + +public interface IContentTemplate +{ + +} \ No newline at end of file diff --git a/Toolkit.Foundation/IContentTemplateDescriptor.cs b/Toolkit.Foundation/IContentTemplateDescriptor.cs new file mode 100644 index 0000000..096876f --- /dev/null +++ b/Toolkit.Foundation/IContentTemplateDescriptor.cs @@ -0,0 +1,10 @@ +namespace Toolkit.Foundation; + +public interface IContentTemplateDescriptor +{ + object Key { get; } + + Type ContentType { get; } + + Type TemplateType { get; } +} \ No newline at end of file diff --git a/Toolkit.Foundation/IContentTemplateDescriptorProvider.cs b/Toolkit.Foundation/IContentTemplateDescriptorProvider.cs new file mode 100644 index 0000000..9475494 --- /dev/null +++ b/Toolkit.Foundation/IContentTemplateDescriptorProvider.cs @@ -0,0 +1,6 @@ +namespace Toolkit.Foundation; + +public interface IContentTemplateDescriptorProvider +{ + IContentTemplateDescriptor? Get(object key); +} diff --git a/Toolkit.Foundation/IDeactivatable.cs b/Toolkit.Foundation/IDeactivatable.cs new file mode 100644 index 0000000..4a598ac --- /dev/null +++ b/Toolkit.Foundation/IDeactivatable.cs @@ -0,0 +1,8 @@ +namespace Toolkit.Foundation; + +public interface IDeactivatable +{ + public event EventHandler? DeactivateHandler; + + public Task Deactivate(); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IDeactivated.cs b/Toolkit.Foundation/IDeactivated.cs new file mode 100644 index 0000000..f640164 --- /dev/null +++ b/Toolkit.Foundation/IDeactivated.cs @@ -0,0 +1,6 @@ +namespace Toolkit.Foundation; + +public interface IDeactivated +{ + Task Deactivated(); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IDeactivating.cs b/Toolkit.Foundation/IDeactivating.cs new file mode 100644 index 0000000..032b5fd --- /dev/null +++ b/Toolkit.Foundation/IDeactivating.cs @@ -0,0 +1,11 @@ +namespace Toolkit.Foundation; + +public interface IDeactivating +{ + Task Deactivating(); +} + +public interface IDeactivating +{ + Task Deactivating(); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IDispatcher.cs b/Toolkit.Foundation/IDispatcher.cs new file mode 100644 index 0000000..d85772d --- /dev/null +++ b/Toolkit.Foundation/IDispatcher.cs @@ -0,0 +1,6 @@ +namespace Toolkit.Foundation; + +public interface IDispatcher +{ + Task InvokeAsync(Action action); +} diff --git a/Toolkit.Foundation/IDisposer.cs b/Toolkit.Foundation/IDisposer.cs new file mode 100644 index 0000000..aff06d6 --- /dev/null +++ b/Toolkit.Foundation/IDisposer.cs @@ -0,0 +1,16 @@ +namespace Toolkit.Foundation; + +public interface IDisposer +{ + void Add(object subject, + params object[] objects); + + TDisposable Replace(object subject, + IDisposable disposer, + TDisposable replacement) where TDisposable : IDisposable; + + void Remove(object subject, + IDisposable disposer); + + void Dispose(object subject); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IFactory.cs b/Toolkit.Foundation/IFactory.cs new file mode 100644 index 0000000..f6837e1 --- /dev/null +++ b/Toolkit.Foundation/IFactory.cs @@ -0,0 +1,12 @@ +namespace Toolkit.Foundation; + +public interface IFactory +{ + TService? Create(TParameter value); +} + + +public interface IFactory +{ + TService? Create(); +} diff --git a/Toolkit.Foundation/IHandler.cs b/Toolkit.Foundation/IHandler.cs new file mode 100644 index 0000000..9bfb4ee --- /dev/null +++ b/Toolkit.Foundation/IHandler.cs @@ -0,0 +1,17 @@ +namespace Toolkit.Foundation; + +public interface IHandler; + +public interface IHandler : + IHandler + where TRequest : + IRequest +{ + Task Handle(TRequest args, + CancellationToken cancellationToken); +} + +public interface IHandler : + IHandler + where TRequest : + IRequest; \ No newline at end of file diff --git a/Framework/Foundation/Extensions/IHostBuilderExtensions.cs b/Toolkit.Foundation/IHostBuilderExtensions.cs similarity index 50% rename from Framework/Foundation/Extensions/IHostBuilderExtensions.cs rename to Toolkit.Foundation/IHostBuilderExtensions.cs index c3bd26d..cb72ce3 100644 --- a/Framework/Foundation/Extensions/IHostBuilderExtensions.cs +++ b/Toolkit.Foundation/IHostBuilderExtensions.cs @@ -1,16 +1,19 @@ using Microsoft.Extensions.Hosting; -namespace Toolkit.Framework.Foundation; +namespace Toolkit.Foundation; public static class IHostBuilderExtensions { - public static IHostBuilder UseContentRoot(this IHostBuilder hostBuilder, string contentRoot, bool createDirectory) + public static IHostBuilder UseContentRoot(this IHostBuilder hostBuilder, + string contentRoot, + bool createDirectory) { - if (!Directory.Exists(contentRoot) && createDirectory) - { + if (createDirectory) + { Directory.CreateDirectory(contentRoot); } - return hostBuilder.UseContentRoot(contentRoot); + hostBuilder.UseContentRoot(contentRoot); + return hostBuilder; } -} \ No newline at end of file +} diff --git a/Toolkit.Foundation/IInitializer.cs b/Toolkit.Foundation/IInitializer.cs new file mode 100644 index 0000000..00a126a --- /dev/null +++ b/Toolkit.Foundation/IInitializer.cs @@ -0,0 +1,6 @@ +namespace Toolkit.Foundation; + +public interface IInitializer +{ + Task Initialize(); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IMediator.cs b/Toolkit.Foundation/IMediator.cs new file mode 100644 index 0000000..74fcb71 --- /dev/null +++ b/Toolkit.Foundation/IMediator.cs @@ -0,0 +1,10 @@ +namespace Toolkit.Foundation; + +public interface IMediator +{ + Task SendAsync(IRequest request, + CancellationToken cancellationToken = default); + + Task SendAsync(object message, CancellationToken + cancellationToken = default); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IMessage.cs b/Toolkit.Foundation/IMessage.cs new file mode 100644 index 0000000..211c872 --- /dev/null +++ b/Toolkit.Foundation/IMessage.cs @@ -0,0 +1,3 @@ +namespace Toolkit.Foundation; + +public interface IMessage; \ No newline at end of file diff --git a/Toolkit.Foundation/INavigateBackHandler.cs b/Toolkit.Foundation/INavigateBackHandler.cs new file mode 100644 index 0000000..50805f1 --- /dev/null +++ b/Toolkit.Foundation/INavigateBackHandler.cs @@ -0,0 +1,5 @@ +namespace Toolkit.Foundation; + +public interface INavigateBackHandler : + INotificationHandler>, + INavigateHandler; \ No newline at end of file diff --git a/Toolkit.Foundation/INavigateHandler.cs b/Toolkit.Foundation/INavigateHandler.cs new file mode 100644 index 0000000..199faad --- /dev/null +++ b/Toolkit.Foundation/INavigateHandler.cs @@ -0,0 +1,7 @@ +namespace Toolkit.Foundation; + +public interface INavigateHandler; + +public interface INavigateHandler : + INotificationHandler>, + INavigateHandler; diff --git a/Toolkit.Foundation/INavigation.cs b/Toolkit.Foundation/INavigation.cs new file mode 100644 index 0000000..4298399 --- /dev/null +++ b/Toolkit.Foundation/INavigation.cs @@ -0,0 +1,7 @@ +namespace Toolkit.Foundation; + +public interface INavigation +{ + Type Type { get; set; } +} + diff --git a/Toolkit.Foundation/INavigationContextCollection.cs b/Toolkit.Foundation/INavigationContextCollection.cs new file mode 100644 index 0000000..e867d10 --- /dev/null +++ b/Toolkit.Foundation/INavigationContextCollection.cs @@ -0,0 +1,4 @@ +namespace Toolkit.Foundation; + +public interface INavigationContextCollection : + IDictionary; diff --git a/Toolkit.Foundation/INavigationContextProvider.cs b/Toolkit.Foundation/INavigationContextProvider.cs new file mode 100644 index 0000000..08ddc03 --- /dev/null +++ b/Toolkit.Foundation/INavigationContextProvider.cs @@ -0,0 +1,9 @@ +namespace Toolkit.Foundation; + +public interface INavigationContextProvider +{ + object? Get(object key); + + bool TryGet(object key, + out object? value); +} \ No newline at end of file diff --git a/Toolkit.Foundation/INavigationProvider.cs b/Toolkit.Foundation/INavigationProvider.cs new file mode 100644 index 0000000..b6255cb --- /dev/null +++ b/Toolkit.Foundation/INavigationProvider.cs @@ -0,0 +1,6 @@ +namespace Toolkit.Foundation; + +public interface INavigationProvider +{ + INavigation? Get(Type type); +} diff --git a/Toolkit.Foundation/INavigationScope.cs b/Toolkit.Foundation/INavigationScope.cs new file mode 100644 index 0000000..6fa029b --- /dev/null +++ b/Toolkit.Foundation/INavigationScope.cs @@ -0,0 +1,10 @@ +namespace Toolkit.Foundation; + +public interface INavigationScope +{ + Task NavigateAsync(string route, object? sender = null, object? context = null, + EventHandler? navigated = null, object[]? parameters = null, CancellationToken cancellationToken = default); + + Task NavigateBackAsync(object? context, CancellationToken cancellationToken = default); +} + diff --git a/Toolkit.Foundation/INavigationViewModel.cs b/Toolkit.Foundation/INavigationViewModel.cs new file mode 100644 index 0000000..d22eb9d --- /dev/null +++ b/Toolkit.Foundation/INavigationViewModel.cs @@ -0,0 +1,7 @@ +namespace Toolkit.Foundation; + +public interface INavigationViewModel : + IObservableViewModel +{ + string Text { get; set; } +} diff --git a/Toolkit.Foundation/INotification.cs b/Toolkit.Foundation/INotification.cs new file mode 100644 index 0000000..1bc2226 --- /dev/null +++ b/Toolkit.Foundation/INotification.cs @@ -0,0 +1,4 @@ +namespace Toolkit.Foundation; + +public interface INotification : + IMessage; \ No newline at end of file diff --git a/Toolkit.Foundation/INotificationHandler.cs b/Toolkit.Foundation/INotificationHandler.cs new file mode 100644 index 0000000..abe34bd --- /dev/null +++ b/Toolkit.Foundation/INotificationHandler.cs @@ -0,0 +1,10 @@ +namespace Toolkit.Foundation; + +public interface INotificationHandler : + IHandler + where TNotification : + INotification +{ + Task Handle(TNotification args, + CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IObservableCollectionViewModel.cs b/Toolkit.Foundation/IObservableCollectionViewModel.cs new file mode 100644 index 0000000..9e12d1e --- /dev/null +++ b/Toolkit.Foundation/IObservableCollectionViewModel.cs @@ -0,0 +1,4 @@ +namespace Toolkit.Foundation; + +public interface IObservableCollectionViewModel : + IObservableViewModel; diff --git a/Toolkit.Foundation/IObservableViewModel.cs b/Toolkit.Foundation/IObservableViewModel.cs new file mode 100644 index 0000000..7d688f4 --- /dev/null +++ b/Toolkit.Foundation/IObservableViewModel.cs @@ -0,0 +1,13 @@ +namespace Toolkit.Foundation; + +public interface IObservableViewModel : + IDisposable +{ + public IDisposer Disposer { get; } + + public IPublisher Publisher { get; } + + public IServiceFactory ServiceFactory { get; } + + public IServiceProvider ServiceProvider { get; } +} \ No newline at end of file diff --git a/Toolkit.Foundation/IPipelineBehavior.cs b/Toolkit.Foundation/IPipelineBehavior.cs new file mode 100644 index 0000000..7bd8b32 --- /dev/null +++ b/Toolkit.Foundation/IPipelineBehavior.cs @@ -0,0 +1,17 @@ +namespace Toolkit.Foundation; + +public interface IPipelineBehavior + where TMessage : IMessage +{ + Task Handle(TMessage message, + HandlerDelegate next, + CancellationToken cancellationToken = default); +} + +public interface IPipelineBehavior + where TNotification : INotification +{ + Task Handle(TNotification notification, + NotificationHandlerDelegate next, + CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IPrimaryConfirmation.cs b/Toolkit.Foundation/IPrimaryConfirmation.cs new file mode 100644 index 0000000..975ed5c --- /dev/null +++ b/Toolkit.Foundation/IPrimaryConfirmation.cs @@ -0,0 +1,12 @@ +namespace Toolkit.Foundation; + +public interface IPrimaryConfirmation +{ + Task Confirm(); +} + +public interface IConfirmation +{ + Task Confirm(); +} + diff --git a/Toolkit.Foundation/IProvider.cs b/Toolkit.Foundation/IProvider.cs new file mode 100644 index 0000000..ce8113b --- /dev/null +++ b/Toolkit.Foundation/IProvider.cs @@ -0,0 +1,11 @@ +namespace Toolkit.Foundation; + +public interface IProvider +{ + TService? Get(TParameter value); +} + +public interface IProvider +{ + TService? Get(); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IProxyService.cs b/Toolkit.Foundation/IProxyService.cs new file mode 100644 index 0000000..bb1747e --- /dev/null +++ b/Toolkit.Foundation/IProxyService.cs @@ -0,0 +1,6 @@ +namespace Toolkit.Foundation; + +public interface IProxyService +{ + TService Proxy { get; } +} diff --git a/Toolkit.Foundation/IProxyServiceCollection.cs b/Toolkit.Foundation/IProxyServiceCollection.cs new file mode 100644 index 0000000..1300292 --- /dev/null +++ b/Toolkit.Foundation/IProxyServiceCollection.cs @@ -0,0 +1,8 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Toolkit.Foundation; + +public interface IProxyServiceCollection +{ + IServiceCollection Services { get; } +} \ No newline at end of file diff --git a/Toolkit.Foundation/IPublisher.cs b/Toolkit.Foundation/IPublisher.cs new file mode 100644 index 0000000..6289413 --- /dev/null +++ b/Toolkit.Foundation/IPublisher.cs @@ -0,0 +1,58 @@ +namespace Toolkit.Foundation; + +public interface IPublisher +{ + public Task Publish(object key, + CancellationToken cancellationToken = default) + where TNotification : + INotification, + new(); + + public Task Publish(TNotification notification, + CancellationToken cancellationToken = default) + where TNotification : + INotification; + + public Task Publish(TNotification notification, + object key, + CancellationToken cancellationToken = default) + where TNotification : + INotification; + + Task PublishUI(TNotification notification, + object key, + CancellationToken cancellationToken = default) + where TNotification : + INotification; + + Task PublishUI(object key, + CancellationToken cancellationToken = default) + where TNotification : + INotification, + new(); + + Task PublishUI(TNotification notification, + CancellationToken cancellationToken = default) + where TNotification : + INotification; + + Task PublishUI(object notification, + CancellationToken cancellationToken = default); + + Task Publish(object notification, + Func, Task> marshal, + object? key = null, + CancellationToken cancellationToken = default); + + Task PublishUIAsync(CancellationToken cancellationToken = default) + where TNotification : + INotification, + new(); + + Task Publish(CancellationToken cancellationToken = default) + where TNotification : + INotification, + new(); + + public Task Publish(object notification, CancellationToken cancellationToken = default); +} diff --git a/Toolkit.Foundation/IRequest.cs b/Toolkit.Foundation/IRequest.cs new file mode 100644 index 0000000..33f891a --- /dev/null +++ b/Toolkit.Foundation/IRequest.cs @@ -0,0 +1,6 @@ +namespace Toolkit.Foundation; + +public interface IRequest : + IMessage; + +public interface IRequest : IRequest; \ No newline at end of file diff --git a/Toolkit.Foundation/ISecondaryConfirmation.cs b/Toolkit.Foundation/ISecondaryConfirmation.cs new file mode 100644 index 0000000..f2588ad --- /dev/null +++ b/Toolkit.Foundation/ISecondaryConfirmation.cs @@ -0,0 +1,6 @@ +namespace Toolkit.Foundation; + +public interface ISecondaryConfirmation +{ + Task Confirm(); +} \ No newline at end of file diff --git a/Toolkit.Foundation/IServiceCollectionExtensions.cs b/Toolkit.Foundation/IServiceCollectionExtensions.cs new file mode 100644 index 0000000..de3c861 --- /dev/null +++ b/Toolkit.Foundation/IServiceCollectionExtensions.cs @@ -0,0 +1,244 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.FileProviders; +using Microsoft.Extensions.FileProviders.Physical; +using Microsoft.Extensions.Hosting; +using System; +using System.Text.Json; +using Toolkit.Foundation; + +namespace Toolkit.Foundation; + +public static class IServiceCollectionExtensions +{ + public static IServiceCollection AddCache(this IServiceCollection services) + where TKey : notnull + where TValue : notnull + { + services.AddScoped, Cache>(); + services.AddTransient(provider => provider.GetService>()!.Select(x => x.Value)); + + return services; + } + + public static IServiceCollection AddCache(this IServiceCollection services) + { + services.AddSingleton, Cache>(); + services.AddTransient(provider => provider.GetService>()!.Select(x => x)); + + return services; + } + + public static IServiceCollection AddComponent(this IServiceCollection services) + where TComponent : class, + IComponent + { + services.AddTransient(); + return services; + } + + public static IServiceCollection AddConfiguration(this IServiceCollection services, + Func> changed) + where TConfiguration : class + where TValue : class, new() + { + services.AddSingleton(new ConfigurationValue(changed)); + services.AddHandler>(); + + return services; + } + + public static IServiceCollection AddConfiguration(this IServiceCollection services) + where TConfiguration : class => + services.AddConfiguration(typeof(TConfiguration).Name, "Settings.json", null); + + public static IServiceCollection AddConfiguration(this IServiceCollection services, + Action configurationDelegate) + where TConfiguration : class, new() + { + TConfiguration configuration = new(); + configurationDelegate.Invoke(configuration); + + return services.AddConfiguration(typeof(TConfiguration).Name, "Settings.json", configuration); + } + + public static IServiceCollection AddConfiguration(this IServiceCollection services, + TConfiguration configuration) + where TConfiguration : class => + services.AddConfiguration(configuration.GetType().Name, "Settings.json", configuration); + + public static IServiceCollection AddConfiguration(this IServiceCollection services, + object configuration) + where TConfiguration : class => + services.AddConfiguration(configuration.GetType().Name, + "Settings.json", (TConfiguration?)configuration); + + public static IServiceCollection AddConfiguration(this IServiceCollection services, + string section, + string path = "Settings.json", + TConfiguration? configuration = null, + Action? serializerDelegate = null) + where TConfiguration : class + { + services.AddSingleton>(provider => + { + JsonSerializerOptions? defaultSerializer = null; + if (serializerDelegate is not null) + { + defaultSerializer = new JsonSerializerOptions(); + serializerDelegate.Invoke(defaultSerializer); + } + + return new ConfigurationSource(provider.GetRequiredService>(), + section, defaultSerializer); + }); + + services.AddSingleton>(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.AddHostedService>(); + services.AddSingleton, ConfigurationReader>(); + services.AddSingleton, ConfigurationWriter>(); + + services.AddTransient>(provider => new ConfigurationFactory(() => + configuration ?? provider.GetRequiredService())); + + services.AddTransient>(); + services.AddTransient, ConfigurationInitializer>(); + + services.AddTransient, WritableConfiguration>(); + + services.AddTransient, Configuration>(); + services.AddTransient(provider => provider.GetRequiredService>().Value); + + return services; + } + + public static IServiceCollection AddTemplate(this IServiceCollection services, + object? key = null, + params object[]? parameters) + { + Type viewModelType = typeof(TViewModel); + Type viewType = typeof(TView); + + key ??= viewModelType.Name.Replace("ViewModel", ""); + + services.AddTransient(viewModelType, provider => + provider.GetRequiredService().Create(parameters)!); + + services.AddTransient(viewType); + + services.AddKeyedTransient(viewModelType, key, (provider, key) => + provider.GetRequiredService().Create(parameters)!); + + services.AddKeyedTransient(viewType, key); + + services.AddTransient(provider => + new ContentTemplateDescriptor(key, viewModelType, viewType, parameters)); + + return services; + } + + public static IServiceCollection AddHandler(this IServiceCollection services, + ServiceLifetime lifetime = ServiceLifetime.Transient) + where THandler : IHandler + { + if (typeof(THandler).GetInterfaces() is Type[] contracts) + { + foreach (Type contract in contracts) + { + if (contract.Name == typeof(INotificationHandler<>).Name && + contract.GetGenericArguments() is { Length: 1 } notificationHandlerArguments) + { + Type notificationType = notificationHandlerArguments[0]; + + Type wrapperType = typeof(NotificationHandlerWrapper<>) + .MakeGenericType(notificationType); + + services.TryAdd(new ServiceDescriptor(typeof(INotificationHandler<>) + .MakeGenericType(notificationType), typeof(THandler), lifetime)); + + services.Add(new ServiceDescriptor(wrapperType, provider => + provider.GetService()?.Create(wrapperType, + provider.GetRequiredService(typeof(INotificationHandler<>).MakeGenericType(notificationType)), + provider.GetServices(typeof(IPipelineBehavior<>) + .MakeGenericType(notificationType)))!, lifetime)); + } + + if (contract.Name == typeof(IHandler<,>).Name && + contract.GetGenericArguments() is { Length: 2 } handlerArguments) + { + Type requestType = handlerArguments[0]; + Type responseType = handlerArguments[1]; + + Type wrapperType = typeof(HandlerWrapper<,>) + .MakeGenericType(requestType, responseType); + + services.TryAdd(new ServiceDescriptor(typeof(THandler), + typeof(THandler), lifetime)); + + services.Add(new ServiceDescriptor(wrapperType, provider => + provider.GetService()?.Create(wrapperType, + provider.GetRequiredService(), + provider.GetServices(typeof(IPipelineBehavior<,>) + .MakeGenericType(requestType, responseType)))!, lifetime)); + } + } + + return services; + } + + return services; + } + + public static IServiceCollection AddInitializer(this IServiceCollection services) + where TInitializer : class, + IInitializer + { + services.AddTransient(); + return services; + } + + public static IServiceCollection AddNavigateHandler(this IServiceCollection services) + where THandler : INavigateHandler, + IHandler + { + IEnumerable contracts = typeof(THandler).GetInterfaces() + .Where(x => x.Name == typeof(INavigateHandler<>).Name || x.Name == typeof(INavigateBackHandler<>).Name); + + foreach (Type contract in contracts) + { + if (contract.GetGenericArguments() is { Length: 1 } arguments) + { + services.AddTransient(provider => new Navigation + { + Type = arguments[0] + }); + } + } + + services.AddHandler(); + return services; + } + public static IServiceCollection AddRange(this IServiceCollection services, + IServiceCollection fromServices) + { + foreach (ServiceDescriptor service in fromServices) + { + services.Add(service); + } + + return services; + } +} \ No newline at end of file diff --git a/Toolkit.Foundation/IServiceFactory.cs b/Toolkit.Foundation/IServiceFactory.cs new file mode 100644 index 0000000..be6aee8 --- /dev/null +++ b/Toolkit.Foundation/IServiceFactory.cs @@ -0,0 +1,8 @@ +namespace Toolkit.Foundation; + +public interface IServiceFactory +{ + object Create(Type type, params object?[]? parameters); + + TService Create(params object?[]? parameters); +} diff --git a/Toolkit.Foundation/IServiceScopeFactory.cs b/Toolkit.Foundation/IServiceScopeFactory.cs new file mode 100644 index 0000000..dc3bae6 --- /dev/null +++ b/Toolkit.Foundation/IServiceScopeFactory.cs @@ -0,0 +1,6 @@ +namespace Toolkit.Foundation; + +public interface IServiceScopeFactory +{ + TService? Create(params object?[] parameters); +} diff --git a/Toolkit.Foundation/IServiceScopeProvider.cs b/Toolkit.Foundation/IServiceScopeProvider.cs new file mode 100644 index 0000000..d0aa9ab --- /dev/null +++ b/Toolkit.Foundation/IServiceScopeProvider.cs @@ -0,0 +1,8 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Toolkit.Foundation; + +public interface IServiceScopeProvider +{ + bool TryGet(TService service, out IServiceScope? serviceScope); +} diff --git a/Toolkit.Foundation/ISubscriber.cs b/Toolkit.Foundation/ISubscriber.cs new file mode 100644 index 0000000..6948bb2 --- /dev/null +++ b/Toolkit.Foundation/ISubscriber.cs @@ -0,0 +1,8 @@ +namespace Toolkit.Foundation; + +public interface ISubscriber +{ + void Remove(object subscriber); + + void Add(object subscriber); +} \ No newline at end of file diff --git a/Toolkit.Foundation/ISubscriptionManager.cs b/Toolkit.Foundation/ISubscriptionManager.cs new file mode 100644 index 0000000..71177e0 --- /dev/null +++ b/Toolkit.Foundation/ISubscriptionManager.cs @@ -0,0 +1,10 @@ +namespace Toolkit.Foundation; + +public interface ISubscriptionManager +{ + IEnumerable GetHandlers(Type notificationType, object key); + + void Remove(object subscriber); + + void Add(object subscriber); +} diff --git a/Toolkit.Foundation/IWritableConfiguration.cs b/Toolkit.Foundation/IWritableConfiguration.cs new file mode 100644 index 0000000..0c537e1 --- /dev/null +++ b/Toolkit.Foundation/IWritableConfiguration.cs @@ -0,0 +1,8 @@ +namespace Toolkit.Foundation; + +public interface IWritableConfiguration + where TConfiguration : + class +{ + void Write(Action updateDelegate); +} diff --git a/Toolkit.Foundation/Insert.cs b/Toolkit.Foundation/Insert.cs new file mode 100644 index 0000000..e97b8eb --- /dev/null +++ b/Toolkit.Foundation/Insert.cs @@ -0,0 +1,3 @@ +namespace Toolkit.Foundation; + +public record Insert(int Index, TValue Value) : INotification; diff --git a/Toolkit.Foundation/KeyAccelerator.cs b/Toolkit.Foundation/KeyAccelerator.cs new file mode 100644 index 0000000..0d3d045 --- /dev/null +++ b/Toolkit.Foundation/KeyAccelerator.cs @@ -0,0 +1,5 @@ +namespace Toolkit.Foundation; + +public record KeyAccelerator(VirtualKey Key, + VirtualKey[]? Modifiers = null) : + IRequest; diff --git a/Toolkit.Foundation/Mediator.cs b/Toolkit.Foundation/Mediator.cs new file mode 100644 index 0000000..c710ed3 --- /dev/null +++ b/Toolkit.Foundation/Mediator.cs @@ -0,0 +1,48 @@ +using System.Reflection; + +namespace Toolkit.Foundation; + +public class Mediator(IServiceProvider provider) : + IMediator +{ + public Task SendAsync(IRequest request, + CancellationToken cancellationToken = default) + { + Type handlerType = typeof(HandlerWrapper<,>).MakeGenericType(request.GetType(), + typeof(TResponse)); + + if (provider.GetService(handlerType) + is object handler) + { + if (handlerType.GetMethod("Handle") is MethodInfo handleMethod) + { + return (Task)handleMethod.Invoke(handler, new object[] { request, cancellationToken })!; + } + } + + return Task.FromResult(default); + } + + public Task SendAsync(object message, + CancellationToken cancellationToken = default) + { + if (message.GetType().GetInterface(typeof(IRequest<>).Name) is Type requestType && + requestType.GetGenericArguments().Length == 1) + { + Type responseType = requestType.GetGenericArguments()[0]; + Type handlerType = typeof(HandlerWrapper<,>).MakeGenericType(message.GetType(), + responseType); + + if (provider.GetService(handlerType) + is object handler) + { + if (handlerType.GetMethod("Handle") is MethodInfo handleMethod) + { + return (Task)handleMethod.Invoke(handler, new object[] { message, cancellationToken })!; + } + } + } + + return Task.FromResult(default); + } +} \ No newline at end of file diff --git a/Toolkit.Foundation/MethodInfoExtensions.cs b/Toolkit.Foundation/MethodInfoExtensions.cs new file mode 100644 index 0000000..374a4f7 --- /dev/null +++ b/Toolkit.Foundation/MethodInfoExtensions.cs @@ -0,0 +1,20 @@ +using System.Reflection; + +namespace Toolkit.Foundation; + +public static class MethodInfoExtensions +{ + public static async Task InvokeAsync(this MethodInfo methodInfo, + object? obj) + { + dynamic result = await (dynamic?)methodInfo.Invoke(obj, null); + return (TResult)result; + } + + public static async Task InvokeAsync(this MethodInfo methodInfo, + object? obj, + params object[] parameters) + { + await (dynamic?)methodInfo.Invoke(obj, parameters); + } +} \ No newline at end of file diff --git a/Toolkit.Foundation/Move.cs b/Toolkit.Foundation/Move.cs new file mode 100644 index 0000000..f3c66d9 --- /dev/null +++ b/Toolkit.Foundation/Move.cs @@ -0,0 +1,3 @@ +namespace Toolkit.Foundation; + +public record Move(int Index, TValue Value) : INotification; \ No newline at end of file diff --git a/Toolkit.Foundation/Navigate.cs b/Toolkit.Foundation/Navigate.cs new file mode 100644 index 0000000..30dce1c --- /dev/null +++ b/Toolkit.Foundation/Navigate.cs @@ -0,0 +1,16 @@ +namespace Toolkit.Foundation; + +public record Navigate(string Route, + object? Context = null, + string? Scope = null, + object? Sender = null, + EventHandler? Navigated = null, + object[]? Parameters = null) : + INotification; + +public record Navigate(object Context, + object Template, + object Content, + object? Sender = null, + object[]? Parameters = null) : + INotification; \ No newline at end of file diff --git a/Toolkit.Foundation/NavigateBack.cs b/Toolkit.Foundation/NavigateBack.cs new file mode 100644 index 0000000..25be518 --- /dev/null +++ b/Toolkit.Foundation/NavigateBack.cs @@ -0,0 +1,7 @@ +namespace Toolkit.Foundation; + +public record NavigateBack(object? Context = null, string? Scope = null) : + INotification; + +public record NavigateBack(object? Context) : + INotification; diff --git a/Toolkit.Foundation/NavigateBackHandler.cs b/Toolkit.Foundation/NavigateBackHandler.cs new file mode 100644 index 0000000..d66c7e4 --- /dev/null +++ b/Toolkit.Foundation/NavigateBackHandler.cs @@ -0,0 +1,22 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Toolkit.Foundation; + +public class NavigateBackHandler(IComponentScopeProvider provider) : + INotificationHandler +{ + public async Task Handle(NavigateBack args, + CancellationToken cancellationToken) + { + if (provider.Get(args.Scope ?? "Default") + is IServiceProvider scope) + { + if (scope.GetService() is INavigationScope navigationScope) + { + await navigationScope.NavigateBackAsync(args.Context, cancellationToken); + } + } + } +} + + diff --git a/Toolkit.Foundation/NavigateHandler.cs b/Toolkit.Foundation/NavigateHandler.cs new file mode 100644 index 0000000..a634319 --- /dev/null +++ b/Toolkit.Foundation/NavigateHandler.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Toolkit.Foundation; + +public class NavigateHandler(IComponentScopeProvider provider) : + INotificationHandler +{ + public async Task Handle(Navigate args, + CancellationToken cancellationToken) + { + if (provider.Get(args.Scope ?? "Default") + is IServiceProvider scope) + { + if (scope.GetService() is INavigationScope navigationScope) + { + await navigationScope.NavigateAsync(args.Route, args.Sender, + args.Context, args.Navigated, args.Parameters, cancellationToken); + } + } + } +} diff --git a/Toolkit.Foundation/NavigatingFrom.cs b/Toolkit.Foundation/NavigatingFrom.cs new file mode 100644 index 0000000..8d8e611 --- /dev/null +++ b/Toolkit.Foundation/NavigatingFrom.cs @@ -0,0 +1,7 @@ +namespace Toolkit.Foundation; + +public record NavigatingFrom(object Content) : + IRequest>; + +public record NavigatingTo(object Content) : + IRequest>; diff --git a/Toolkit.Foundation/Navigation.cs b/Toolkit.Foundation/Navigation.cs new file mode 100644 index 0000000..4a1c6e0 --- /dev/null +++ b/Toolkit.Foundation/Navigation.cs @@ -0,0 +1,8 @@ +namespace Toolkit.Foundation; + +public record Navigation : + INavigation +{ + public required Type Type { get; set; } +} + diff --git a/Toolkit.Foundation/NavigationChanged.cs b/Toolkit.Foundation/NavigationChanged.cs new file mode 100644 index 0000000..6545fd0 --- /dev/null +++ b/Toolkit.Foundation/NavigationChanged.cs @@ -0,0 +1,4 @@ +namespace Toolkit.Foundation; + +public record NavigationChanged(TValue? Value) : + INotification; \ No newline at end of file diff --git a/Toolkit.Foundation/NavigationContextAttribute.cs b/Toolkit.Foundation/NavigationContextAttribute.cs new file mode 100644 index 0000000..651c12d --- /dev/null +++ b/Toolkit.Foundation/NavigationContextAttribute.cs @@ -0,0 +1,12 @@ +namespace Toolkit.Foundation; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] +public class NavigationContextAttribute : Attribute +{ + public NavigationContextAttribute(string name) + { + Name = name; + } + + public string Name { get; } +} diff --git a/Toolkit.Foundation/NavigationContextCollection.cs b/Toolkit.Foundation/NavigationContextCollection.cs new file mode 100644 index 0000000..a36d908 --- /dev/null +++ b/Toolkit.Foundation/NavigationContextCollection.cs @@ -0,0 +1,4 @@ +namespace Toolkit.Foundation; + +public class NavigationContextCollection : Dictionary, + INavigationContextCollection; diff --git a/Toolkit.Foundation/NavigationContextProvider.cs b/Toolkit.Foundation/NavigationContextProvider.cs new file mode 100644 index 0000000..74865bb --- /dev/null +++ b/Toolkit.Foundation/NavigationContextProvider.cs @@ -0,0 +1,24 @@ +namespace Toolkit.Foundation; + +public class NavigationContextProvider(INavigationContextCollection contexts) : + INavigationContextProvider +{ + public object? Get(object key) => + contexts.TryGetValue(key, out object? target) ? target : default; + + public bool TryGet(object name, + out object? value) + { + if (contexts.TryGetValue(name, + out object? target)) + { + value = target; + return true; + } + else + { + value = null; + return false; + } + } +} diff --git a/Toolkit.Foundation/NavigationProvider.cs b/Toolkit.Foundation/NavigationProvider.cs new file mode 100644 index 0000000..2135e07 --- /dev/null +++ b/Toolkit.Foundation/NavigationProvider.cs @@ -0,0 +1,16 @@ +namespace Toolkit.Foundation; + +public class NavigationProvider(IEnumerable navigations) : + INavigationProvider +{ + public INavigation? Get(Type type) + { + if (navigations.FirstOrDefault(x => type == x.Type || + type.BaseType == x.Type) is INavigation navigation) + { + return navigation; + } + + return default; + } +} diff --git a/Toolkit.Foundation/NavigationScope.cs b/Toolkit.Foundation/NavigationScope.cs new file mode 100644 index 0000000..374cb41 --- /dev/null +++ b/Toolkit.Foundation/NavigationScope.cs @@ -0,0 +1,104 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Toolkit.Foundation; + +public class NavigationScope(IPublisher publisher, + IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + INavigationProvider navigationProvider, + INavigationContextProvider navigationContextProvider, + IContentTemplateDescriptorProvider contentTemplateDescriptorProvider) : + INavigationScope +{ + public async Task NavigateAsync(string route, object? sender = null, object? context = null, + EventHandler? navigated = null, object[]? parameters = null, CancellationToken cancellationToken = default) + { + string[] segments = route.Split('/'); + int segmentCount = segments.Length; + int currentSegmentIndex = 0; + + foreach (object segment in segments) + { + currentSegmentIndex++; + + if (contentTemplateDescriptorProvider.Get(segment) + is IContentTemplateDescriptor descriptor) + { + Dictionary? arguments = parameters?.OfType>() + .ToDictionary(x => x.Key, x => x.Value, StringComparer.InvariantCultureIgnoreCase) ?? []; + + IEnumerable? mappedParameters = descriptor.ContentType + .GetConstructors() + .FirstOrDefault()? + .GetParameters() + .Select(parameter => parameter?.Name is not null && arguments + .TryGetValue(parameter.Name, out object? argument) ? argument : default) + .Where(argument => argument is not null); + + parameters = [.. parameters?.Where(x => x.GetType() != typeof(KeyValuePair)) ?? + Enumerable.Empty(), + .. mappedParameters ?? Enumerable.Empty()]; + + if (serviceProvider.GetRequiredKeyedService(descriptor.TemplateType, segment) is object view) + { + if ((parameters is { Length: > 0 } + ? serviceFactory.Create(descriptor.ContentType, parameters) + : serviceProvider.GetRequiredKeyedService(descriptor.ContentType, segment)) is object viewModel) + { + if (context is not null) + { + if (navigationContextProvider.TryGet(context, out object? scopedContext)) + { + context = scopedContext; + } + } + else + { + context = view; + } + + if (context is not null) + { + if (navigationProvider.Get(context is Type type ? type : context.GetType()) + is INavigation navigation) + { + Type navigateType = typeof(Navigate<>).MakeGenericType(navigation.Type); + if (Activator.CreateInstance(navigateType, [context, view, viewModel, sender, parameters]) is object navigate) + { + await publisher.Publish(navigate, cancellationToken); + if (currentSegmentIndex == segmentCount) + { + navigated?.Invoke(this, EventArgs.Empty); + } + } + } + } + } + } + } + } + } + + public async Task NavigateBackAsync(object? context, + CancellationToken cancellationToken = default) + { + if (context is not null) + { + navigationContextProvider.TryGet(context, out context); + } + + if (context is not null) + { + if (navigationProvider.Get(context is Type type ? type : context.GetType()) + is INavigation navigation) + { + Type navigateType = typeof(NavigateBack<>).MakeGenericType(navigation.Type); + if (Activator.CreateInstance(navigateType, [context]) is object navigate) + { + await publisher.Publish(navigate, cancellationToken); + } + } + } + } +} + diff --git a/Toolkit.Foundation/NavigationTargetAttribute.cs b/Toolkit.Foundation/NavigationTargetAttribute.cs new file mode 100644 index 0000000..29bc568 --- /dev/null +++ b/Toolkit.Foundation/NavigationTargetAttribute.cs @@ -0,0 +1,8 @@ +namespace HyperX.UI.Windows; + +[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] +public class NavigationTargetAttribute(string name) : + Attribute +{ + public string Name => name; +} diff --git a/Toolkit.Foundation/NavigationViewModel.cs b/Toolkit.Foundation/NavigationViewModel.cs new file mode 100644 index 0000000..f9052e7 --- /dev/null +++ b/Toolkit.Foundation/NavigationViewModel.cs @@ -0,0 +1,31 @@ +using CommunityToolkit.Mvvm.ComponentModel; + +namespace Toolkit.Foundation; + +public partial class NavigationViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer, + string text) : + ObservableViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer), + INavigationViewModel +{ + [ObservableProperty] + private string? text = text; +} + +public partial class NavigationViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer, + string text) : + ObservableViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer), + INavigationViewModel + where TNavigationViewModel : + INavigationViewModel +{ + [ObservableProperty] + private string? text = text; +} diff --git a/Toolkit.Foundation/NotificationAttribute.cs b/Toolkit.Foundation/NotificationAttribute.cs new file mode 100644 index 0000000..d178ddd --- /dev/null +++ b/Toolkit.Foundation/NotificationAttribute.cs @@ -0,0 +1,7 @@ +namespace Toolkit.Foundation; + +[AttributeUsage(AttributeTargets.Class, Inherited = false)] +public class NotificationAttribute(object key) : Attribute +{ + public object Key => key; +} \ No newline at end of file diff --git a/Toolkit.Foundation/NotificationHandlerDelegate.cs b/Toolkit.Foundation/NotificationHandlerDelegate.cs new file mode 100644 index 0000000..2237a3a --- /dev/null +++ b/Toolkit.Foundation/NotificationHandlerDelegate.cs @@ -0,0 +1,5 @@ +namespace Toolkit.Foundation; + +public delegate Task NotificationHandlerDelegate(TNotification notification, + CancellationToken cancellationToken) + where TNotification : INotification; diff --git a/Toolkit.Foundation/NotificationHandlerWrapper.cs b/Toolkit.Foundation/NotificationHandlerWrapper.cs new file mode 100644 index 0000000..100165a --- /dev/null +++ b/Toolkit.Foundation/NotificationHandlerWrapper.cs @@ -0,0 +1,25 @@ +namespace Toolkit.Foundation; + +public class NotificationHandlerWrapper(INotificationHandler handler, + IEnumerable> pipelineBehaviours) + where TNotification : INotification +{ + private readonly IEnumerable> pipelineBehaviours = + pipelineBehaviours.Reverse(); + + public async Task Handle(TNotification notification, + CancellationToken cancellationToken) + { + NotificationHandlerDelegate currentHandler = handler.Handle; + foreach (IPipelineBehavior behavior in pipelineBehaviours) + { + NotificationHandlerDelegate previousHandler = currentHandler; + currentHandler = async (args, token) => + { + await behavior.Handle(args, previousHandler, token); + }; + } + + await currentHandler(notification, cancellationToken); + } +} diff --git a/Toolkit.Foundation/ObjectExtensions.cs b/Toolkit.Foundation/ObjectExtensions.cs new file mode 100644 index 0000000..9cad647 --- /dev/null +++ b/Toolkit.Foundation/ObjectExtensions.cs @@ -0,0 +1,32 @@ +using System.Reflection; + +namespace Toolkit.Foundation; + +public static class ObjectExtensions +{ + public static object? GetPropertyValue(this object obj, Func selector) + { + Type type = obj.GetType(); + + object? key = selector(); + if (type.GetProperty($"{key}") is PropertyInfo property + && property.GetValue(obj) is { } value) + { + return value; + } + + return null; + } + + public static TAttribute? GetAttribute(this object obj) + where TAttribute : Attribute + { + Type type = obj.GetType(); + if (type.GetAttribute() is TAttribute attribute) + { + return attribute; + } + + return null; + } +} \ No newline at end of file diff --git a/Toolkit.Foundation/ObservableCollectionViewModel.cs b/Toolkit.Foundation/ObservableCollectionViewModel.cs new file mode 100644 index 0000000..81c2712 --- /dev/null +++ b/Toolkit.Foundation/ObservableCollectionViewModel.cs @@ -0,0 +1,415 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System.Collections; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Reactive.Disposables; + +namespace Toolkit.Foundation; +public partial class ObservableCollectionViewModel : + ObservableObject, + IObservableCollectionViewModel, + IInitializer, + IActivated, + IDeactivating, + IDeactivated, + IDeactivatable, + IList, + IList, + IReadOnlyList, + INotifyCollectionChanged, + INotificationHandler>, + INotificationHandler>, + INotificationHandler>, + INotificationHandler>, + INotificationHandler> + where TViewModel : + notnull +{ + private readonly ObservableCollection collection = []; + + [ObservableProperty] + private bool isInitialized; + + public ObservableCollectionViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer) + { + ServiceProvider = serviceProvider; + ServiceFactory = serviceFactory; + Publisher = publisher; + Disposer = disposer; + + subscriber.Add(this); + + collection.CollectionChanged += OnCollectionChanged; + } + + public ObservableCollectionViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer, + IEnumerable items) + { + ServiceProvider = serviceProvider; + ServiceFactory = serviceFactory; + Publisher = publisher; + Disposer = disposer; + + subscriber.Add(this); + + collection.CollectionChanged += OnCollectionChanged; + AddRange(items); + } + + public event NotifyCollectionChangedEventHandler? CollectionChanged; + + public event EventHandler? DeactivateHandler; + + public int Count => collection.Count; + + public IDisposer Disposer { get; private set; } + + bool IList.IsFixedSize => false; + + bool ICollection.IsReadOnly => false; + + bool IList.IsReadOnly => false; + + bool ICollection.IsSynchronized => false; + + public IPublisher Publisher { get; private set; } + + public IServiceFactory ServiceFactory { get; private set; } + + public IServiceProvider ServiceProvider { get; private set; } + + object ICollection.SyncRoot => this; + + public TViewModel this[int index] + { + get => collection[index]; + set => SetItem(index, value); + } + + object? IList.this[int index] + { + get => collection[index]; + set + { + TViewModel? item = default; + + try + { + item = (TViewModel)value!; + } + catch (InvalidCastException) + { + + } + + this[index] = item!; + } + } + + public virtual Task Activated() => + Task.CompletedTask; + + public TViewModel Add() + { + TViewModel? item = ServiceFactory.Create(); + + Add(item); + return item; + } + + public TViewModel Add(params object?[] parameters) + where T : TViewModel + { + T? item = ServiceFactory.Create(parameters); + Add(item); + + return item; + } + + public TViewModel Add() + where T : + TViewModel + { + T? item = ServiceFactory.Create(); + Add(item); + + return item; + } + + public void Add(TViewModel item) + { + int index = collection.Count; + InsertItem(index, item); + } + + public void Add(object item) + { + int index = collection.Count; + InsertItem(index, (TViewModel)item); + } + + int IList.Add(object? value) + { + TViewModel? item = default; + + try + { + item = (TViewModel)value!; + } + catch (InvalidCastException) + { + + } + + Add(item!); + return Count - 1; + } + + public void AddRange(IEnumerable items) + { + foreach (TViewModel? item in items) + { + Add(item); + } + } + + public void Clear() + { + foreach (TViewModel item in collection) + { + Disposer.Dispose(item); + } + + ClearItems(); + } + + public bool Contains(TViewModel item) => + collection.Contains(item); + + bool IList.Contains(object? value) => + IsCompatibleObject(value) && Contains((TViewModel)value!); + + public void CopyTo(TViewModel[] array, int index) => + collection.CopyTo(array, index); + + void ICollection.CopyTo(Array array, int index) => + collection.CopyTo((TViewModel[])array, index); + + public Task Deactivate() + { + DeactivateHandler?.Invoke(this, new EventArgs()); + return Task.CompletedTask; + } + + public virtual Task Deactivated() => + Task.CompletedTask; + + public virtual Task Deactivating() => + Task.CompletedTask; + + public virtual void Dispose() + { + GC.SuppressFinalize(this); + Disposer.Dispose(this); + } + + public IEnumerator GetEnumerator() => + collection.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => + ((IEnumerable)collection).GetEnumerator(); + + public Task Handle(Remove args, + CancellationToken cancellationToken) + { + foreach (TViewModel item in this.ToList()) + { + if (args.Value is not null && args.Value.Equals(item)) + { + Remove(item); + } + } + + return Task.CompletedTask; + } + + public Task Handle(Create args, + CancellationToken cancellationToken) + { + if (args.Value is TViewModel item) + { + Add(item); + } + + return Task.CompletedTask; + } + + public Task Handle(Insert args, + CancellationToken cancellationToken) + { + if (args.Value is TViewModel item) + { + Insert(args.Index, item); + } + + return Task.CompletedTask; + } + + public Task Handle(Move args, + CancellationToken cancellationToken) + { + if (args.Value is TViewModel item) + { + Move(args.Index, item); + } + + return Task.CompletedTask; + } + + public Task Handle(Replace args, + CancellationToken cancellationToken) + { + if (args.Value is TViewModel item) + { + Replace(args.Index, item); + } + + return Task.CompletedTask; + } + + public int IndexOf(TViewModel item) => + collection.IndexOf(item); + + int IList.IndexOf(object? value) => + IsCompatibleObject(value) ? + IndexOf((TViewModel)value!) : -1; + + public async Task Initialize() + { + if (isInitialized) + { + return; + } + + isInitialized = true; + + object? key = this.GetAttribute() + is NotificationAttribute attribute + ? this.GetPropertyValue(() => attribute.Key) is { } value ? value : attribute.Key + : null; + + await Publisher.PublishUI(new Enumerate(key)); + } + + public void Insert(int index, TViewModel item) => + InsertItem(index, item); + + void IList.Insert(int index, + object? value) + { + if (value is TViewModel item) + { + Insert(index, item); + } + } + + public bool Move(int index, TViewModel item) + { + int oldIndex = collection.IndexOf(item); + if (oldIndex < 0) + { + return false; + } + + RemoveItem(oldIndex); + Insert(index, item); + + return true; + } + + public bool Remove(TViewModel item) + { + int index = collection.IndexOf(item); + if (index < 0) + { + return false; + } + + Disposer.Dispose(item); + RemoveItem(index); + + return true; + } + + void IList.Remove(object? value) + { + if (IsCompatibleObject(value)) + { + Remove((TViewModel)value!); + } + } + + public void RemoveAt(int index) => + RemoveItem(index); + + public bool Replace(int index, + TViewModel item) + { + if (index <= Count - 1) + { + RemoveItem(index); + } + else + { + index = Count; + } + + Insert(index, item); + return true; + } + + protected virtual void ClearItems() => + collection.Clear(); + + protected virtual void InsertItem(int index, + TViewModel item) + { + Disposer.Add(this, item); + Disposer.Add(item, item, Disposable.Create(() => + { + if (item is IList collection) + { + collection.Clear(); + } + })); + + collection.Insert(index, item); + } + + protected virtual void RemoveItem(int index) => + collection.RemoveAt(index); + + protected virtual void SetItem(int index, TViewModel item) => + collection[index] = item; + + private static bool IsCompatibleObject(object? value) => + (value is TViewModel) || (value == null && default(TViewModel) == null); + + private void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs args) => + CollectionChanged?.Invoke(this, args); +} + +public class ObservableCollectionViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer) : + ObservableCollectionViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer); \ No newline at end of file diff --git a/Toolkit.Foundation/ObservableViewModel.cs b/Toolkit.Foundation/ObservableViewModel.cs new file mode 100644 index 0000000..2f73260 --- /dev/null +++ b/Toolkit.Foundation/ObservableViewModel.cs @@ -0,0 +1,72 @@ +using CommunityToolkit.Mvvm.ComponentModel; + +namespace Toolkit.Foundation; + +public partial class ObservableViewModel : + ObservableObject, + IObservableViewModel, + IInitializer, + IActivated, + IDeactivating, + IDeactivated, + IDeactivatable +{ + [ObservableProperty] + private bool isInitialized; + + public ObservableViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer) + { + ServiceProvider = serviceProvider; + ServiceFactory = serviceFactory; + Publisher = publisher; + Disposer = disposer; + + subscriber.Add(this); + } + + public event EventHandler? DeactivateHandler; + + public IDisposer Disposer { get; } + + public IPublisher Publisher { get; } + + public IServiceFactory ServiceFactory { get; } + + public IServiceProvider ServiceProvider { get; } + + public virtual Task Activated() => + Task.CompletedTask; + + public Task Deactivate() + { + DeactivateHandler?.Invoke(this, new EventArgs()); + return Task.CompletedTask; + } + + public virtual Task Deactivated() => + Task.CompletedTask; + + public virtual Task Deactivating() => + Task.CompletedTask; + + public void Dispose() + { + GC.SuppressFinalize(this); + Disposer.Dispose(this); + } + + public Task Initialize() + { + if (IsInitialized) + { + return Task.CompletedTask; + } + + IsInitialized = true; + return Task.CompletedTask; + } +} diff --git a/Toolkit.Foundation/ProxyService.cs b/Toolkit.Foundation/ProxyService.cs new file mode 100644 index 0000000..03a1eb2 --- /dev/null +++ b/Toolkit.Foundation/ProxyService.cs @@ -0,0 +1,7 @@ +namespace Toolkit.Foundation; + +public class ProxyService(TService proxy) : + IProxyService +{ + public TService Proxy { get; private set; } = proxy; +} \ No newline at end of file diff --git a/Toolkit.Foundation/ProxyServiceCollection.cs b/Toolkit.Foundation/ProxyServiceCollection.cs new file mode 100644 index 0000000..16fca72 --- /dev/null +++ b/Toolkit.Foundation/ProxyServiceCollection.cs @@ -0,0 +1,15 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Toolkit.Foundation; + +public class ProxyServiceCollection : + IProxyServiceCollection +{ + public ProxyServiceCollection(Action configureDelegate) + { + Services = new ServiceCollection(); + configureDelegate.Invoke(Services); + } + + public IServiceCollection Services { get; private set; } +} \ No newline at end of file diff --git a/Toolkit.Foundation/Publisher.cs b/Toolkit.Foundation/Publisher.cs new file mode 100644 index 0000000..12622bc --- /dev/null +++ b/Toolkit.Foundation/Publisher.cs @@ -0,0 +1,106 @@ +using Microsoft.Extensions.DependencyInjection; +using System.Reflection; + +namespace Toolkit.Foundation; + +public class Publisher(ISubscriptionManager subscriptionManager, + IServiceProvider provider, + IDispatcher dispatcher) : + IPublisher +{ + public Task Publish(object key, + CancellationToken cancellationToken = default) + where TNotification : + INotification, + new() => Publish(new TNotification(), async args => await args(), + key, cancellationToken); + + public Task Publish(TNotification notification, + CancellationToken cancellationToken = default) + where TNotification : + INotification => Publish(notification, async args => await args(), + null, cancellationToken); + + public Task Publish(TNotification notification, + object key, + CancellationToken cancellationToken = default) + where TNotification : + INotification => Publish(notification, + async args => await args(), key, cancellationToken); + + public async Task Publish(object notification, + Func, Task> marshal, + object? key = null, + CancellationToken cancellationToken = default) + { + Type notificationType = notification.GetType(); + + List handlers = provider.GetServices(typeof(NotificationHandlerWrapper<>) + .MakeGenericType(notificationType)).ToList(); + + foreach (object? handler in subscriptionManager + .GetHandlers(notificationType, key!)) + { + handlers.Add(handler); + } + + foreach (object? handler in handlers) + { + if (handler is not null) + { + Type? handlerType = handler.GetType(); + MethodInfo? handleMethod = handlerType.GetMethod("Handle", + [notificationType, typeof(CancellationToken)]); + + if (handleMethod is not null) + { + await marshal(() => (Task)handleMethod.Invoke(handler, new object[] + { notification, cancellationToken })!); + } + } + } + } + + public Task Publish(object notification, + CancellationToken cancellationToken = default) => Publish(notification, + async args => await args(), + null, cancellationToken); + + public Task Publish(CancellationToken cancellationToken = default) + where TNotification : + INotification, new() => Publish(new TNotification(), + async args => await args(), + null, cancellationToken); + + public Task PublishUI(object key, + CancellationToken cancellationToken = default) + where TNotification : + INotification, new() => Publish(new TNotification(), + args => dispatcher.InvokeAsync(async () => await args()), + key, cancellationToken); + + public Task PublishUI(TNotification notification, + CancellationToken cancellationToken = default) + where TNotification : + INotification => Publish(notification, + args => dispatcher.InvokeAsync(async () => await args()), + null, cancellationToken); + + public Task PublishUI(TNotification notification, + object key, + CancellationToken cancellationToken = default) + where TNotification : + INotification => Publish(notification, + args => dispatcher.InvokeAsync(async () => await args()), + key, cancellationToken); + public Task PublishUIAsync(CancellationToken cancellationToken = default) + where TNotification : + INotification, new() => Publish(new TNotification(), + args => dispatcher.InvokeAsync(async () => await args()), + null, cancellationToken); + + public Task PublishUI(object notification, + CancellationToken cancellationToken = default) => Publish(notification, args => + dispatcher.InvokeAsync(async () => await args()), + null, cancellationToken); +} diff --git a/Toolkit.Foundation/Remove.cs b/Toolkit.Foundation/Remove.cs new file mode 100644 index 0000000..54d190d --- /dev/null +++ b/Toolkit.Foundation/Remove.cs @@ -0,0 +1,5 @@ + +namespace Toolkit.Foundation; + +public record Remove(TValue Value) : + INotification; \ No newline at end of file diff --git a/Toolkit.Foundation/Replace.cs b/Toolkit.Foundation/Replace.cs new file mode 100644 index 0000000..6441149 --- /dev/null +++ b/Toolkit.Foundation/Replace.cs @@ -0,0 +1,6 @@ + +namespace Toolkit.Foundation; + +public record Replace(int Index, TValue Value, object? Target = null) : + INotification; + diff --git a/Toolkit.Foundation/Request.cs b/Toolkit.Foundation/Request.cs new file mode 100644 index 0000000..a5d5fb7 --- /dev/null +++ b/Toolkit.Foundation/Request.cs @@ -0,0 +1,12 @@ +namespace Toolkit.Foundation; + +public record Request : + INotification +{ + +} + +public class Request +{ + public static Request Create() => new(); +} \ No newline at end of file diff --git a/Toolkit.Foundation/Response.cs b/Toolkit.Foundation/Response.cs new file mode 100644 index 0000000..f1a7248 --- /dev/null +++ b/Toolkit.Foundation/Response.cs @@ -0,0 +1,4 @@ +namespace Toolkit.Foundation; + +public record Response(TValue Value) : + INotification; \ No newline at end of file diff --git a/Toolkit.Foundation/ServiceFactory.cs b/Toolkit.Foundation/ServiceFactory.cs new file mode 100644 index 0000000..39e892e --- /dev/null +++ b/Toolkit.Foundation/ServiceFactory.cs @@ -0,0 +1,11 @@ +namespace Toolkit.Foundation; + +public class ServiceFactory(Func factory) : + IServiceFactory +{ + public TService Create(params object?[]? parameters) => + (TService)factory(typeof(TService), parameters); + + public object Create(Type type, params object?[]? parameters) => + factory(type, parameters); +} \ No newline at end of file diff --git a/Toolkit.Foundation/ServiceScopeFactory.cs b/Toolkit.Foundation/ServiceScopeFactory.cs new file mode 100644 index 0000000..e8b114e --- /dev/null +++ b/Toolkit.Foundation/ServiceScopeFactory.cs @@ -0,0 +1,26 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Toolkit.Foundation; + +public class ServiceScopeFactory(IServiceScopeFactory serviceScopeFactory, + ICache cache) : + IServiceScopeFactory + where TService : notnull +{ + public TService? Create(params object?[] parameters) + { + if (serviceScopeFactory.CreateScope() is IServiceScope serviceScope) + { + if (serviceScope.ServiceProvider.GetService() is IServiceFactory serviceFactory) + { + if (serviceFactory.Create(parameters) is TService service) + { + cache.Add(service, serviceScope); + return service; + } + } + } + + return default; + } +} \ No newline at end of file diff --git a/Toolkit.Foundation/ServiceScopeProvider.cs b/Toolkit.Foundation/ServiceScopeProvider.cs new file mode 100644 index 0000000..11ccc9b --- /dev/null +++ b/Toolkit.Foundation/ServiceScopeProvider.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.DependencyInjection; + +namespace Toolkit.Foundation; + +public class ServiceScopeProvider(ICache cache) : + IServiceScopeProvider + where TService : notnull +{ + public bool TryGet(TService service, + out IServiceScope? serviceScope) + { + if (cache.TryGetValue(service, out IServiceScope? value)) + { + serviceScope = value; + return true; + } + + serviceScope = null; + return false; + } +} diff --git a/Toolkit.Foundation/SetupRequiredAttribute.cs b/Toolkit.Foundation/SetupRequiredAttribute.cs new file mode 100644 index 0000000..6f2c67d --- /dev/null +++ b/Toolkit.Foundation/SetupRequiredAttribute.cs @@ -0,0 +1,7 @@ +namespace Toolkit.Foundation; + +[AttributeUsage(AttributeTargets.Class, Inherited = false)] +public class NavigationRouteAttribute(string route) : Attribute +{ + public string Route => route; +} diff --git a/Toolkit.Foundation/StartProcess.cs b/Toolkit.Foundation/StartProcess.cs new file mode 100644 index 0000000..c2cae16 --- /dev/null +++ b/Toolkit.Foundation/StartProcess.cs @@ -0,0 +1,3 @@ +namespace Toolkit.Foundation; + +public record StartProcess(string Process) : IRequest; \ No newline at end of file diff --git a/Toolkit.Foundation/Started.cs b/Toolkit.Foundation/Started.cs new file mode 100644 index 0000000..9180311 --- /dev/null +++ b/Toolkit.Foundation/Started.cs @@ -0,0 +1,4 @@ +namespace Toolkit.Foundation; + +public record Started : + INotification; \ No newline at end of file diff --git a/Toolkit.Foundation/Subscriber.cs b/Toolkit.Foundation/Subscriber.cs new file mode 100644 index 0000000..8d13d8f --- /dev/null +++ b/Toolkit.Foundation/Subscriber.cs @@ -0,0 +1,11 @@ +namespace Toolkit.Foundation; + +public class Subscriber(ISubscriptionManager subscriptionManager) : + ISubscriber +{ + public void Remove(object subscriber) => + subscriptionManager.Remove(subscriber); + + public void Add(object subscriber) => + subscriptionManager.Add(subscriber); +} \ No newline at end of file diff --git a/Toolkit.Foundation/SubscriptionCollection.cs b/Toolkit.Foundation/SubscriptionCollection.cs new file mode 100644 index 0000000..67cbbc4 --- /dev/null +++ b/Toolkit.Foundation/SubscriptionCollection.cs @@ -0,0 +1,6 @@ +using System.Collections.Concurrent; + +namespace Toolkit.Foundation; + +public class SubscriptionCollection : + ConcurrentDictionary>; diff --git a/Toolkit.Foundation/SubscriptionManager.cs b/Toolkit.Foundation/SubscriptionManager.cs new file mode 100644 index 0000000..2d8eae3 --- /dev/null +++ b/Toolkit.Foundation/SubscriptionManager.cs @@ -0,0 +1,78 @@ +using System.Reflection; + +namespace Toolkit.Foundation; + +public class SubscriptionManager(SubscriptionCollection subscriptions) : + ISubscriptionManager +{ + public IEnumerable GetHandlers(Type notificationType, object key) + { + if (subscriptions.TryGetValue($"{(key is not null ? $"{key}:" : "")}{notificationType}", + out List? subscribers)) + { + foreach (WeakReference weakRef in subscribers.ToArray()) + { + object? target = weakRef.Target; + if (target != null) + { + yield return target; + } + else + { + subscribers.Remove(weakRef); + } + } + } + } + + public void Remove(object subscriber) + { + Type handlerType = subscriber.GetType(); + object? key = GetKeyFromHandler(subscriber); + foreach (Type interfaceType in GetHandlerInterfaces(handlerType)) + { + if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType) + { + if (subscriptions.TryGetValue($"{(key is not null ? $"{key}:" : "")}{argumentType}", out List? subscribers)) + { + for (int i = subscribers.Count - 1; i >= 0; i--) + { + if (!subscribers[i].IsAlive || subscribers[i].Target == subscriber) + { + subscribers.RemoveAt(i); + } + } + } + } + } + } + + public void Add(object subscriber) + { + Type handlerType = subscriber.GetType(); + object? key = GetKeyFromHandler(subscriber); + foreach (Type interfaceType in GetHandlerInterfaces(handlerType)) + { + if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType) + { + subscriptions.AddOrUpdate($"{(key is not null ? $"{key}:" : "")}{argumentType}", _ => new List { new(subscriber) }, (_, collection) => + { + collection.Add(new WeakReference(subscriber)); + return collection; + }); + } + } + } + + private static object? GetKeyFromHandler(object handler) + { + return handler.GetAttribute() + is NotificationAttribute attribute + ? handler.GetPropertyValue(() => attribute.Key) is { } value ? value : attribute.Key + : null; + } + + private static IEnumerable GetHandlerInterfaces(Type handlerType) => + handlerType.GetInterfaces().Where(interfaceType => interfaceType.IsGenericType && + interfaceType.GetGenericTypeDefinition() == typeof(INotificationHandler<>)); +} diff --git a/Toolkit.Foundation/Toolkit.Foundation.csproj b/Toolkit.Foundation/Toolkit.Foundation.csproj new file mode 100644 index 0000000..e27f1b3 --- /dev/null +++ b/Toolkit.Foundation/Toolkit.Foundation.csproj @@ -0,0 +1,12 @@ + + + net8.0 + enable + enable + + + + + + + diff --git a/Toolkit.Foundation/TypeExtensions.cs b/Toolkit.Foundation/TypeExtensions.cs new file mode 100644 index 0000000..76ea051 --- /dev/null +++ b/Toolkit.Foundation/TypeExtensions.cs @@ -0,0 +1,17 @@ +using System.Reflection; + +namespace Toolkit.Foundation; + +public static class TypeExtensions +{ + public static TAttribute? GetAttribute(this Type type) + where TAttribute : Attribute + { + if (type.GetCustomAttribute() is TAttribute attribute) + { + return attribute; + } + + return null; + } +} diff --git a/Framework/Foundation/Lifecycles/Unit.cs b/Toolkit.Foundation/Unit.cs similarity index 58% rename from Framework/Foundation/Lifecycles/Unit.cs rename to Toolkit.Foundation/Unit.cs index 1caa6ca..1b9e8e7 100644 --- a/Framework/Foundation/Lifecycles/Unit.cs +++ b/Toolkit.Foundation/Unit.cs @@ -1,12 +1,15 @@ -namespace Toolkit.Framework.Foundation; +namespace Toolkit.Foundation; -public readonly struct Unit : IEquatable, IComparable, IComparable +public readonly struct Unit : + IEquatable, + IComparable, + IComparable { - private static readonly Unit _value = new(); + private static readonly Unit value = new(); - public static ref readonly Unit Value => ref _value; + public static ref readonly Unit Value => ref value; - public static ValueTask ValueTask => new ValueTask(_value); + public static ValueTask ValueTask => new(value); public int CompareTo(Unit other) => 0; @@ -23,4 +26,4 @@ public readonly struct Unit : IEquatable, IComparable, IComparable public static bool operator !=(Unit _, Unit __) => false; public override string ToString() => "()"; -} +} \ No newline at end of file diff --git a/Toolkit.Foundation/ValueViewModel.cs b/Toolkit.Foundation/ValueViewModel.cs new file mode 100644 index 0000000..da03c02 --- /dev/null +++ b/Toolkit.Foundation/ValueViewModel.cs @@ -0,0 +1,21 @@ +using CommunityToolkit.Mvvm.ComponentModel; + +namespace Toolkit.Foundation; + +public partial class ValueViewModel(IServiceProvider serviceProvider, + IServiceFactory serviceFactory, + IPublisher publisher, + ISubscriber subscriber, + IDisposer disposer) : + ObservableViewModel(serviceProvider, serviceFactory, publisher, subscriber, disposer) +{ + [ObservableProperty] + private TValue? value; + + protected virtual void OnChanged(TValue? value) + { + + } + + partial void OnValueChanged(TValue? value) => OnChanged(value); +} diff --git a/Toolkit.Foundation/VirtualKey.cs b/Toolkit.Foundation/VirtualKey.cs new file mode 100644 index 0000000..67ca644 --- /dev/null +++ b/Toolkit.Foundation/VirtualKey.cs @@ -0,0 +1,175 @@ +namespace Toolkit.Foundation; + +public enum VirtualKey +{ + None = 0, + LeftButton = 1, + RightButton = 2, + Cancel = 3, + MiddleButton = 4, + XButton1 = 5, + XButton2 = 6, + Back = 8, + Tab = 9, + Clear = 12, + Enter = 13, + Shift = 16, + Control = 17, + Menu = 18, + Pause = 19, + CapitalLock = 20, + Kana = 21, + Hangul = 21, + Junja = 23, + Final = 24, + Hanja = 25, + Kanji = 25, + Escape = 27, + Convert = 28, + NonConvert = 29, + Accept = 30, + ModeChange = 31, + Space = 32, + PageUp = 33, + PageDown = 34, + End = 35, + Home = 36, + Left = 37, + Up = 38, + Right = 39, + Down = 40, + Select = 41, + Print = 42, + Execute = 43, + Snapshot = 44, + Insert = 45, + Delete = 46, + Help = 47, + Number0 = 48, + Number1 = 49, + Number2 = 50, + Number3 = 51, + Number4 = 52, + Number5 = 53, + Number6 = 54, + Number7 = 55, + Number8 = 56, + Number9 = 57, + A = 65, + B = 66, + C = 67, + D = 68, + E = 69, + F = 70, + G = 71, + H = 72, + I = 73, + J = 74, + K = 75, + L = 76, + M = 77, + N = 78, + O = 79, + P = 80, + Q = 81, + R = 82, + S = 83, + T = 84, + U = 85, + V = 86, + W = 87, + X = 88, + Y = 89, + Z = 90, + LeftWindows = 91, + RightWindows = 92, + Application = 93, + Sleep = 95, + NumberPad0 = 96, + NumberPad1 = 97, + NumberPad2 = 98, + NumberPad3 = 99, + NumberPad4 = 100, + NumberPad5 = 101, + NumberPad6 = 102, + NumberPad7 = 103, + NumberPad8 = 104, + NumberPad9 = 105, + Multiply = 106, + Add = 107, + Separator = 108, + Subtract = 109, + Decimal = 110, + Divide = 111, + F1 = 112, + F2 = 113, + F3 = 114, + F4 = 115, + F5 = 116, + F6 = 117, + F7 = 118, + F8 = 119, + F9 = 120, + F10 = 121, + F11 = 122, + F12 = 123, + F13 = 124, + F14 = 125, + F15 = 126, + F16 = 127, + F17 = 128, + F18 = 129, + F19 = 130, + F20 = 131, + F21 = 132, + F22 = 133, + F23 = 134, + F24 = 135, + NavigationView = 136, + NavigationMenu = 137, + NavigationUp = 138, + NavigationDown = 139, + NavigationLeft = 140, + NavigationRight = 141, + NavigationAccept = 142, + NavigationCancel = 143, + NumberKeyLock = 144, + Scroll = 145, + LeftShift = 160, + RightShift = 161, + LeftControl = 162, + RightControl = 163, + LeftMenu = 164, + RightMenu = 165, + GoBack = 166, + GoForward = 167, + Refresh = 168, + Stop = 169, + Search = 170, + Favorites = 171, + GoHome = 172, + GamepadA = 195, + GamepadB = 196, + GamepadX = 197, + GamepadY = 198, + GamepadRightShoulder = 199, + GamepadLeftShoulder = 200, + GamepadLeftTrigger = 201, + GamepadRightTrigger = 202, + GamepadDPadUp = 203, + GamepadDPadDown = 204, + GamepadDPadLeft = 205, + GamepadDPadRight = 206, + GamepadMenu = 207, + GamepadView = 208, + GamepadLeftThumbstickButton = 209, + GamepadRightThumbstickButton = 210, + GamepadLeftThumbstickUp = 211, + GamepadLeftThumbstickDown = 212, + GamepadLeftThumbstickRight = 213, + GamepadLeftThumbstickLeft = 214, + GamepadRightThumbstickUp = 215, + GamepadRightThumbstickDown = 216, + GamepadRightThumbstickRight = 217, + GamepadRightThumbstickLeft = 218 +} diff --git a/Toolkit.Foundation/WritableConfiguration.cs b/Toolkit.Foundation/WritableConfiguration.cs new file mode 100644 index 0000000..4f1f4f1 --- /dev/null +++ b/Toolkit.Foundation/WritableConfiguration.cs @@ -0,0 +1,9 @@ +namespace Toolkit.Foundation; + +public class WritableConfiguration(IConfigurationWriter writer) : + IWritableConfiguration + where TConfiguration : + class +{ + public void Write(Action updateDelegate) => writer.Write(updateDelegate); +} diff --git a/Toolkit.sln b/Toolkit.sln index f6750d5..6086fe2 100644 --- a/Toolkit.sln +++ b/Toolkit.sln @@ -3,7 +3,19 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.4.33110.190 MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Toolkit.Foundation", "Toolkit.Foundation\Toolkit.Foundation.csproj", "{66968F8D-689E-49D8-9370-DFF099C56202}" +EndProject Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {66968F8D-689E-49D8-9370-DFF099C56202}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {66968F8D-689E-49D8-9370-DFF099C56202}.Debug|Any CPU.Build.0 = Debug|Any CPU + {66968F8D-689E-49D8-9370-DFF099C56202}.Release|Any CPU.ActiveCfg = Release|Any CPU + {66968F8D-689E-49D8-9370-DFF099C56202}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection