Meditor SourceGen doesn't work for our needs right now, so let's build something on top of their library that allows us to do manual registration for now.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Metadata;
|
||||
|
||||
namespace Toolkit.Controls.Avalonia;
|
||||
|
||||
@@ -10,13 +11,14 @@ public class ContentIcon : FluentAvalonia.UI.Controls.FAIconElement
|
||||
public static readonly StyledProperty<IDataTemplate> IconTemplateProperty =
|
||||
AvaloniaProperty.Register<ContentIcon, IDataTemplate>("IconTemplate");
|
||||
|
||||
public static readonly StyledProperty<object> IconProperty =
|
||||
AvaloniaProperty.Register<ContentIcon, object>("Icon");
|
||||
public static readonly StyledProperty<object> ContentProperty =
|
||||
AvaloniaProperty.Register<ContentIcon, object>("Content");
|
||||
|
||||
public object Icon
|
||||
[Content]
|
||||
public object Content
|
||||
{
|
||||
get => GetValue(IconProperty);
|
||||
set => SetValue(IconProperty, value);
|
||||
get => GetValue(ContentProperty);
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
|
||||
private ContentControl? content;
|
||||
@@ -64,7 +66,7 @@ public class ContentIcon : FluentAvalonia.UI.Controls.FAIconElement
|
||||
{
|
||||
content = new ContentControl();
|
||||
|
||||
content.Bind(ContentControl.ContentProperty, this.GetBindingObservable(IconProperty));
|
||||
content.Bind(ContentControl.ContentProperty, this.GetBindingObservable(ContentProperty));
|
||||
content.Bind(ContentControl.ContentTemplateProperty, this.GetBindingObservable(IconTemplateProperty));
|
||||
|
||||
LogicalChildren.Add(content);
|
||||
|
||||
@@ -1,8 +1,34 @@
|
||||
using Avalonia.Styling;
|
||||
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<NavigationViewItemInvokedEventArgs> Invoked;
|
||||
|
||||
Type IStyleable.StyleKey => typeof(FluentAvalonia.UI.Controls.NavigationViewItem);
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs args)
|
||||
{
|
||||
navigationView = this.FindAncestorOfType<NavigationView>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using Avalonia.Controls;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Toolkit.Framework.Foundation;
|
||||
|
||||
@@ -12,9 +10,11 @@ public static class IServiceCollectionExtensions
|
||||
{
|
||||
serviceCollection.TryAddSingleton<INavigationRouteDescriptorCollection, NavigationRouteDescriptorCollection>();
|
||||
|
||||
serviceCollection.TryAddTransient<Navigation<Frame>, FrameNavigation>();
|
||||
serviceCollection.TryAddTransient<Navigation<ContentDialog>, ContentDialogNavigation>();
|
||||
serviceCollection.TryAddTransient<Navigation<ContentControl>, ContentControlNavigation>();
|
||||
serviceCollection.AddHandler<NavigationRouteHandler>();
|
||||
serviceCollection.AddHandler<NavigateHandler>();
|
||||
serviceCollection.AddHandler<FrameNavigationHandler>();
|
||||
serviceCollection.AddHandler<ContentDialogNavigationHandler>();
|
||||
serviceCollection.AddHandler<ContentControlNavigationHandler>();
|
||||
|
||||
return serviceCollection;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Avalonia.Controls;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Mediator;
|
||||
using System.Diagnostics;
|
||||
using Toolkit.Framework.Foundation;
|
||||
|
||||
namespace Toolkit.Framework.Avalonia;
|
||||
|
||||
@@ -1,19 +1,42 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Mediator;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
namespace Toolkit.Framework.Foundation;
|
||||
|
||||
public static class IServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddHandler<TRequestHandler>(this IServiceCollection serviceCollection)
|
||||
public static IServiceCollection AddHandler<TRequestHandler>(this IServiceCollection services) where TRequestHandler : notnull
|
||||
{
|
||||
serviceCollection.TryAdd(new ServiceDescriptor(typeof(TRequestHandler), typeof(TRequestHandler), ServiceLifetime.Transient));
|
||||
return serviceCollection;
|
||||
if (typeof(TRequestHandler).GetInterface(typeof(IRequestHandler<,>).Name) is { } contract)
|
||||
{
|
||||
if (contract.GetGenericArguments() is { Length: 2 } arguments)
|
||||
{
|
||||
Type requestType = arguments[0];
|
||||
Type responseType = arguments[1];
|
||||
Type wrapperType = typeof(RequestClassHandlerWrapper<,>).MakeGenericType(requestType, responseType);
|
||||
|
||||
services.TryAdd(new ServiceDescriptor(typeof(TRequestHandler), typeof(TRequestHandler), ServiceLifetime.Transient));
|
||||
services.Add(new ServiceDescriptor(wrapperType,
|
||||
sp =>
|
||||
{
|
||||
return sp.GetService<IServiceFactory>()?.Create(wrapperType, sp.GetRequiredService<TRequestHandler>(), sp.GetServices(typeof(IPipelineBehavior<,>).MakeGenericType(requestType, responseType)))!;
|
||||
},
|
||||
ServiceLifetime.Transient
|
||||
));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddFoundation(this IServiceCollection serviceCollection)
|
||||
{
|
||||
serviceCollection.AddSingleton<IServiceFactory>(provider => new ServiceFactory(provider.GetService, (instanceType, parameters) => ActivatorUtilities.CreateInstance(provider, instanceType, parameters!)))
|
||||
serviceCollection
|
||||
.AddSingleton<IMediator, Mediator>()
|
||||
.AddHandler<InitializeHandler>()
|
||||
.AddSingleton<IServiceFactory>(provider => new ServiceFactory(provider.GetService, (instanceType, parameters) => ActivatorUtilities.CreateInstance(provider, instanceType, parameters!)))
|
||||
.AddSingleton<IInitialization, Initialization>(provider => new Initialization(() =>
|
||||
{
|
||||
return serviceCollection.Where(x => x.ServiceType.GetInterfaces()
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
using Mediator;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Toolkit.Framework.Foundation;
|
||||
|
||||
public class Mediator : IMediator
|
||||
{
|
||||
private readonly IServiceProvider factory;
|
||||
|
||||
public Mediator(IServiceProvider factory)
|
||||
{
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<TResponse> CreateStream<TResponse>(IStreamQuery<TResponse> query, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<TResponse> CreateStream<TResponse>(IStreamRequest<TResponse> request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<TResponse> CreateStream<TResponse>(IStreamCommand<TResponse> command, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<object?> CreateStream(object request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ValueTask Publish<TNotification>(TNotification notification, CancellationToken cancellationToken = default) where TNotification : INotification
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ValueTask Publish(object notification, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ValueTask<TResponse> Send<TResponse>(IRequest<TResponse> 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<TResponse> Send<TResponse>(ICommand<TResponse> command, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ValueTask<TResponse> Send<TResponse>(IQuery<TResponse> query, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ValueTask<object?> Send(object message, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using Mediator;
|
||||
|
||||
namespace Toolkit.Framework.Foundation;
|
||||
|
||||
public class RequestClassHandlerWrapper<TRequest, TResponse> where TRequest : class, IRequest<TResponse>
|
||||
{
|
||||
private readonly MessageHandlerDelegate<TRequest, TResponse> handler;
|
||||
|
||||
public RequestClassHandlerWrapper(IRequestHandler<TRequest, TResponse> concreteHandler,
|
||||
IEnumerable<IPipelineBehavior<TRequest, TResponse>> pipelineBehaviours)
|
||||
{
|
||||
MessageHandlerDelegate<TRequest, TResponse> handler = concreteHandler.Handle;
|
||||
foreach (var pipeline in pipelineBehaviours.Reverse())
|
||||
{
|
||||
MessageHandlerDelegate<TRequest, TResponse> handlerCopy = handler;
|
||||
IPipelineBehavior<TRequest, TResponse> pipelineCopy = pipeline;
|
||||
|
||||
handler = (TRequest message, CancellationToken cancellationToken) => pipelineCopy.Handle(message, cancellationToken, handlerCopy);
|
||||
}
|
||||
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public ValueTask<TResponse> Handle(TRequest request, CancellationToken cancellationToken) => handler(request, cancellationToken);
|
||||
}
|
||||
Reference in New Issue
Block a user