reduce mediator duffs

This commit is contained in:
TheXamlGuy
2024-01-07 18:02:04 +00:00
parent 05150c2c03
commit 2e8af23784
24 changed files with 77 additions and 255 deletions
@@ -1,4 +1,3 @@
using Hyperbar.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@@ -1,4 +1,3 @@
using Hyperbar.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@@ -10,7 +9,6 @@ public class PrimaryWidgetProvider :
public void Create(HostBuilderContext comtext, IServiceCollection services) =>
services.AddConfiguration(comtext.Configuration.GetSection(nameof(PrimaryWidgetConfiguration)),
PrimaryWidgetConfiguration.Defaults)
.AddTransient<WidgetComponentMappingFactory>()
.AddTransient(provider => provider.GetRequiredService<WidgetComponentMappingFactory>().Create())
.AddHandler<WidgetComponentMappingHandler>()
.AddWidgetTemplate<PrimaryWidgetViewModel>();
}
@@ -1,4 +1,4 @@
namespace Hyperbar.Windows.Primary;
namespace Hyperbar.Windows.Primary;
public class PrimaryWidgetViewModel :
ObservableCollectionViewModel<IWidgetComponentViewModel>,
@@ -0,0 +1,20 @@
namespace Hyperbar.Windows.Primary;
public class WidgetComponentMappingHandler(PrimaryWidgetConfiguration configuration,
IServiceFactory service,
IMediator mediator) :
IMappingHandler<PrimaryWidgetConfiguration, IEnumerable<IWidgetComponentViewModel>>
{
public IEnumerable<IWidgetComponentViewModel> Handle()
{
foreach (IPrimaryCommandConfiguration item in configuration)
{
if (item is KeyAcceleratorCommandConfiguration keyAcceleratorCommand)
{
yield return service.Create<WidgetButtonViewModel>(keyAcceleratorCommand.Icon, new Action(async () =>
await mediator.SendAsync(new KeyAcceleratorCommand(VirtualKey.LeftWindows))));
}
}
}
}
@@ -1,30 +0,0 @@
namespace Hyperbar.Windows.Primary;
public class WidgetComponentMappingFactory :
IMappingFactory<PrimaryWidgetConfiguration, IEnumerable<IWidgetComponentViewModel>>
{
private readonly PrimaryWidgetConfiguration configuration;
private readonly IServiceFactory service;
private readonly IMediator mediator;
public WidgetComponentMappingFactory(PrimaryWidgetConfiguration configuration,
IServiceFactory service,
IMediator mediator)
{
this.configuration = configuration;
this.service = service;
this.mediator = mediator;
}
public IEnumerable<IWidgetComponentViewModel> Create()
{
foreach (IPrimaryCommandConfiguration item in configuration)
{
if (item is KeyAcceleratorCommandConfiguration keyAcceleratorCommand)
{
yield return service.Create<WidgetButtonViewModel>(keyAcceleratorCommand.Icon, new Action(() =>
mediator.Send(new KeyAcceleratorCommand(VirtualKey.LeftWindows))));
}
}
}
}
+1 -3
View File
@@ -1,11 +1,9 @@
using Hyperbar.Extensions;
using Hyperbar.Widget.Contextual;
using Hyperbar.Widget.Contextual;
using Hyperbar.Windows.Controls;
using Hyperbar.Windows.Primary;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Microsoft.UI.Xaml;
namespace Hyperbar.Windows;
@@ -1,5 +1,4 @@
using Hyperbar.Extensions;
using Hyperbar.Windows.Interop;
using Hyperbar.Windows.Interop;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@@ -32,7 +31,7 @@ namespace Hyperbar.Windows
isolatedServices.AddSingleton<IVirtualKeyboard, VirtualKeyboard>();
isolatedServices.AddSingleton<IMediator, Mediator>();
isolatedServices.AddHandler<KeyAcceleratorCommandHandler>();
isolatedServices.AddHandler<KeyAcceleratorHandler>();
isolatedServices.AddTransient<IWidgetView, WidgetView>();
isolatedServices.AddContentTemplate<WidgetButtonViewModel, WidgetButtonView>();
@@ -2,8 +2,8 @@
namespace Hyperbar.Windows;
public class KeyAcceleratorCommandHandler(IVirtualKeyboard virtualKeyboard) :
ICommandHandler<KeyAcceleratorCommand>
public class KeyAcceleratorHandler(IVirtualKeyboard virtualKeyboard) :
IRequestHandler<KeyAcceleratorCommand>
{
public ValueTask<Unit> Handle(KeyAcceleratorCommand command,
CancellationToken cancellationToken)
+1 -1
View File
@@ -2,4 +2,4 @@
public record KeyAcceleratorCommand(VirtualKey Key,
VirtualKey[]? Modifiers = null) :
ICommand;
IRequest;
@@ -1,12 +1,27 @@
namespace Hyperbar;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using System.Threading;
namespace Hyperbar;
public record ConfigurationChanged<TConfiguration>(TConfiguration Configuration) : INotification
where TConfiguration :
class;
public class ConfigurationInitializer<TConfiguration>(DefaultConfiguration<TConfiguration> defaults,
IConfigurationWriter<TConfiguration> writer) : IInitializer
IConfigurationWriter<TConfiguration> writer,
IOptionsMonitor<TConfiguration> options,
IMediator mediator) : IInitializer
where TConfiguration :
class, new()
{
public Task InitializeAsync()
{
options.OnChange(args =>
{
mediator.PublishAsync(new ConfigurationChanged<TConfiguration>(args));
});
writer.Write(defaults.Configuration);
return Task.CompletedTask;
}
@@ -6,14 +6,14 @@ using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using System.Text.Json;
namespace Hyperbar.Extensions;
namespace Hyperbar;
public static class IServiceCollectionExtensions
{
public static IServiceCollection AddHandler<THandler>(this IServiceCollection serviceCollection,
public static IServiceCollection AddHandler<THandler>(this IServiceCollection services,
ServiceLifetime lifetime = ServiceLifetime.Transient)
where THandler :
notnull
IHandler
{
if (typeof(THandler).GetInterface(typeof(INotificationHandler<>).Name) is { } notificationContract)
{
@@ -21,13 +21,13 @@ public static class IServiceCollectionExtensions
{
Type notificationType = arguments[0];
serviceCollection.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), ServiceLifetime.Singleton));
serviceCollection.Add(new ServiceDescriptor(typeof(INotificationHandler<>).MakeGenericType(notificationType),
services.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), ServiceLifetime.Singleton));
services.Add(new ServiceDescriptor(typeof(INotificationHandler<>).MakeGenericType(notificationType),
provider => provider.GetRequiredService<THandler>(), lifetime));
}
}
if (typeof(THandler).GetInterface(typeof(IRequestHandler<,>).Name) is { } requestContract)
if (typeof(THandler).GetInterface(typeof(IHandler<,>).Name) is { } requestContract)
{
if (requestContract.GetGenericArguments() is { Length: 2 } arguments)
{
@@ -36,8 +36,8 @@ public static class IServiceCollectionExtensions
Type wrapperType = typeof(RequestClassHandlerWrapper<,>).MakeGenericType(requestType, responseType);
serviceCollection.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), lifetime));
serviceCollection.Add(new ServiceDescriptor(wrapperType,
services.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), lifetime));
services.Add(new ServiceDescriptor(wrapperType,
provider => provider.GetService<IServiceFactory>()?.Create(wrapperType,
provider.GetRequiredService<THandler>(),
provider.GetServices(typeof(IPipelineBehavior<,>).MakeGenericType(requestType, responseType)))!,
@@ -46,44 +46,19 @@ public static class IServiceCollectionExtensions
}
}
if (typeof(THandler).GetInterface(typeof(ICommandHandler<,>).Name) is { } commandContract)
if (typeof(THandler).GetInterface(typeof(IMappingHandler<,>).Name) is { } mappingContract)
{
if (commandContract.GetGenericArguments() is { Length: 2 } arguments)
if (mappingContract.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,
provider => provider.GetService<IServiceFactory>()?.Create(wrapperType,
provider.GetRequiredService<THandler>(),
provider.GetServices(typeof(IPipelineBehavior<,>).MakeGenericType(requestType, responseType)))!,
lifetime
));
services.AddTransient(typeof(THandler));
services.AddTransient(responseType, provider => ((dynamic)provider.GetRequiredService<THandler>()).Handle());
}
}
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,
provider => provider.GetService<IServiceFactory>()?.Create(wrapperType,
provider.GetRequiredService<THandler>(),
provider.GetServices(typeof(IPipelineBehavior<,>).MakeGenericType(requestType, responseType)))!,
lifetime
));
}
}
return serviceCollection;
return services;
}
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection services,
@@ -1,6 +1,6 @@
namespace Hyperbar;
public interface IMappingFactory<TFrom, TTo>
public interface IMapping<TFrom, TTo>
{
TTo Create();
}
@@ -1,28 +0,0 @@
namespace Hyperbar;
public class CommandClassHandlerWrapper<TRequest, TResponse>
where TRequest :
class,
ICommand<TResponse>
{
private readonly MessageHandlerDelegate<TRequest, TResponse> handler;
public CommandClassHandlerWrapper(ICommandHandler<TRequest, TResponse> concreteHandler,
IEnumerable<IPipelineBehavior<TRequest, TResponse>> pipelineBehaviours)
{
MessageHandlerDelegate<TRequest, TResponse> handler = concreteHandler.Handle;
foreach (IPipelineBehavior<TRequest, TResponse>? pipeline in pipelineBehaviours.Reverse())
{
MessageHandlerDelegate<TRequest, TResponse> handlerCopy = handler;
IPipelineBehavior<TRequest, TResponse> pipelineCopy = pipeline;
handler = (TRequest message, CancellationToken cancellationToken) =>
pipelineCopy.Handle(message, handlerCopy, cancellationToken);
}
this.handler = handler;
}
public ValueTask<TResponse> Handle(TRequest request, CancellationToken cancellationToken) => handler(request, cancellationToken);
}
-5
View File
@@ -1,5 +0,0 @@
namespace Hyperbar;
public interface ICommand : ICommand<Unit>;
public interface ICommand<out TResponse> : IMessage;
-13
View File
@@ -1,13 +0,0 @@
namespace Hyperbar;
public interface ICommandHandler<in TCommand> : ICommandHandler<TCommand, Unit>
where TCommand :
ICommand<Unit>;
public interface ICommandHandler<in TCommand, TResponse>
where TCommand :
ICommand<TResponse>
{
ValueTask<TResponse> Handle(TCommand command,
CancellationToken cancellationToken);
}
@@ -1,6 +1,9 @@
namespace Hyperbar;
public interface IRequestHandler<in TRequest, TResponse>
public interface IHandler;
public interface IHandler<in TRequest, TResponse> :
IHandler
where TRequest :
IRequest<TResponse>
{
@@ -9,7 +12,7 @@ public interface IRequestHandler<in TRequest, TResponse>
}
public interface IRequestHandler<in TRequest> :
IRequestHandler<TRequest, Unit>
IHandler<TRequest, Unit>
where TRequest :
IRequest<Unit>
{
+7
View File
@@ -0,0 +1,7 @@
namespace Hyperbar;
public interface IMappingHandler<TFrom, TTo> :
IHandler
{
TTo Handle();
}
-8
View File
@@ -7,17 +7,9 @@ public interface IMediator
where TNotification :
INotification;
void Send<TResponse>(ICommand<TResponse> command);
ValueTask<TResponse> SendAsync<TResponse>(IRequest<TResponse> request,
CancellationToken cancellationToken = default);
ValueTask<TResponse> SendAsync<TResponse>(ICommand<TResponse> command,
CancellationToken cancellationToken = default);
ValueTask<TResponse> SendAsync<TResponse>(IQuery<TResponse> query,
CancellationToken cancellationToken = default);
ValueTask<object?> SendAsync(object message, CancellationToken
cancellationToken = default);
-3
View File
@@ -1,3 +0,0 @@
namespace Hyperbar;
public interface IQuery<out TResponse> : IMessage;
-9
View File
@@ -1,9 +0,0 @@
namespace Hyperbar;
public interface IQueryHandler<in TQuery, TResponse>
where TQuery :
IQuery<TResponse>
{
ValueTask<TResponse> Handle(TQuery query,
CancellationToken cancellationToken);
}
+3
View File
@@ -0,0 +1,3 @@
namespace Hyperbar;
public class Map<TFrom, TTo>;
-70
View File
@@ -50,45 +50,6 @@ public class Mediator(IServiceProvider provider) :
return default;
}
public ValueTask<TResponse> SendAsync<TResponse>(ICommand<TResponse> command,
CancellationToken cancellationToken = default)
{
dynamic? handler = provider.GetService(typeof(CommandClassHandlerWrapper<,>)
.MakeGenericType(command.GetType(), typeof(TResponse)));
if (handler is not null)
{
return handler.Handle((dynamic)command, cancellationToken);
}
return default;
}
public void Send<TResponse>(ICommand<TResponse> command)
{
dynamic? handler = provider.GetService(typeof(CommandClassHandlerWrapper<,>)
.MakeGenericType(command.GetType(), typeof(TResponse)));
if (handler is not null)
{
_ = handler.Handle((dynamic)command, default(CancellationToken));
}
}
public ValueTask<TResponse> SendAsync<TResponse>(IQuery<TResponse> query,
CancellationToken cancellationToken = default)
{
dynamic? handler = provider.GetService(typeof(QueryClassHandlerWrapper<,>)
.MakeGenericType(query.GetType(), typeof(TResponse)));
if (handler is not null)
{
return handler.Handle((dynamic)query, cancellationToken);
}
return default;
}
public ValueTask<object?> SendAsync(object message,
CancellationToken cancellationToken = default)
{
@@ -108,37 +69,6 @@ public class Mediator(IServiceProvider provider) :
}
}
if (message.GetType().GetInterface(typeof(ICommand<>).Name) is { } commandType)
{
if (commandType.GetGenericArguments() is { Length: 1 } arguments)
{
Type responseType = arguments[0];
dynamic? handler = provider.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 = provider.GetService(typeof(QueryClassHandlerWrapper<,>)
.MakeGenericType(message.GetType(), responseType));
if (handler is not null)
{
return handler.Handle((dynamic)message, cancellationToken);
}
}
}
return default;
}
@@ -1,29 +0,0 @@
namespace Hyperbar;
public class QueryClassHandlerWrapper<TRequest, TResponse>
where TRequest :
class,
IQuery<TResponse>
{
private readonly MessageHandlerDelegate<TRequest, TResponse> handler;
public QueryClassHandlerWrapper(IQueryHandler<TRequest, TResponse> concreteHandler,
IEnumerable<IPipelineBehavior<TRequest, TResponse>> pipelineBehaviours)
{
MessageHandlerDelegate<TRequest, TResponse> handler = concreteHandler.Handle;
foreach (IPipelineBehavior<TRequest, TResponse>? pipeline in pipelineBehaviours.Reverse())
{
MessageHandlerDelegate<TRequest, TResponse> handlerCopy = handler;
IPipelineBehavior<TRequest, TResponse> pipelineCopy = pipeline;
handler = (TRequest message, CancellationToken cancellationToken) =>
pipelineCopy.Handle(message, handlerCopy, cancellationToken);
}
this.handler = handler;
}
public ValueTask<TResponse> Handle(TRequest request, CancellationToken cancellationToken) =>
handler(request, cancellationToken);
}
@@ -7,7 +7,7 @@ public class RequestClassHandlerWrapper<TRequest, TResponse>
{
private readonly MessageHandlerDelegate<TRequest, TResponse> handler;
public RequestClassHandlerWrapper(IRequestHandler<TRequest, TResponse> concreteHandler,
public RequestClassHandlerWrapper(IHandler<TRequest, TResponse> concreteHandler,
IEnumerable<IPipelineBehavior<TRequest, TResponse>> pipelineBehaviours)
{
MessageHandlerDelegate<TRequest, TResponse> handler = concreteHandler.Handle;