reduce mediator duffs
This commit is contained in:
@@ -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>();
|
||||
}
|
||||
@@ -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,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
-2
@@ -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)
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface ICommand : ICommand<Unit>;
|
||||
|
||||
public interface ICommand<out TResponse> : IMessage;
|
||||
@@ -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>
|
||||
{
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface IMappingHandler<TFrom, TTo> :
|
||||
IHandler
|
||||
{
|
||||
TTo Handle();
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface IQuery<out TResponse> : IMessage;
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface IQueryHandler<in TQuery, TResponse>
|
||||
where TQuery :
|
||||
IQuery<TResponse>
|
||||
{
|
||||
ValueTask<TResponse> Handle(TQuery query,
|
||||
CancellationToken cancellationToken);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
namespace Hyperbar;
|
||||
|
||||
public class Map<TFrom, TTo>;
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user