Mediator work
This commit is contained in:
@@ -0,0 +1,12 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,34 +1,20 @@
|
|||||||
using Mediator;
|
using Mediator;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace Toolkit.Framework.Foundation;
|
namespace Toolkit.Framework.Foundation;
|
||||||
|
|
||||||
public static class IServiceCollectionExtensions
|
public static class IServiceCollectionExtensions
|
||||||
{
|
{
|
||||||
public static IServiceCollection AddHandler<TRequestHandler>(this IServiceCollection services) where TRequestHandler : notnull
|
public static IServiceCollection AddConfiguration<TConfiguration>(this IServiceCollection serviceCollection, IConfiguration configuration) where TConfiguration : class, new()
|
||||||
{
|
{
|
||||||
if (typeof(TRequestHandler).GetInterface(typeof(IRequestHandler<,>).Name) is { } contract)
|
serviceCollection.Configure<TConfiguration>(configuration);
|
||||||
{
|
serviceCollection.AddTransient(provider => provider.GetService<IOptionsMonitor<TConfiguration>>()!.CurrentValue);
|
||||||
if (contract.GetGenericArguments() is { Length: 2 } arguments)
|
serviceCollection.AddTransient<ConfigurationInitializer<TConfiguration>>();
|
||||||
{
|
|
||||||
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));
|
return serviceCollection;
|
||||||
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)
|
public static IServiceCollection AddFoundation(this IServiceCollection serviceCollection)
|
||||||
@@ -50,4 +36,80 @@ public static class IServiceCollectionExtensions
|
|||||||
|
|
||||||
return serviceCollection;
|
return serviceCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddHandler<THandler>(this IServiceCollection services, ServiceLifetime lifetime = ServiceLifetime.Transient) where THandler : notnull
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
services.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), lifetime));
|
||||||
|
services.Add(new ServiceDescriptor(wrapperType,
|
||||||
|
sp =>
|
||||||
|
{
|
||||||
|
return sp.GetService<IServiceFactory>()?.Create(wrapperType, sp.GetRequiredService<THandler>(), 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);
|
||||||
|
|
||||||
|
services.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), lifetime));
|
||||||
|
services.Add(new ServiceDescriptor(wrapperType,
|
||||||
|
sp =>
|
||||||
|
{
|
||||||
|
return sp.GetService<IServiceFactory>()?.Create(wrapperType, sp.GetRequiredService<THandler>(), 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);
|
||||||
|
|
||||||
|
services.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), lifetime));
|
||||||
|
services.Add(new ServiceDescriptor(wrapperType,
|
||||||
|
sp =>
|
||||||
|
{
|
||||||
|
return sp.GetService<IServiceFactory>()?.Create(wrapperType, sp.GetRequiredService<THandler>(), sp.GetServices(typeof(IPipelineBehavior<,>).MakeGenericType(requestType, responseType)))!;
|
||||||
|
},
|
||||||
|
lifetime
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IServiceCollection AddWritableConfiguration<TConfiguration>(this IServiceCollection serviceCollection, IConfiguration configuration) where TConfiguration : class, new()
|
||||||
|
{
|
||||||
|
serviceCollection.Configure<TConfiguration>(configuration);
|
||||||
|
serviceCollection.AddTransient<IConfigurationWriter<TConfiguration>, ConfigurationWriter<TConfiguration>>();
|
||||||
|
serviceCollection.AddTransient(provider => provider.GetService<IOptionsMonitor<TConfiguration>>()!.CurrentValue);
|
||||||
|
serviceCollection.AddHandler<WriteHandler<TConfiguration>>();
|
||||||
|
serviceCollection.AddTransient<ConfigurationInitializer<TConfiguration>>();
|
||||||
|
|
||||||
|
return serviceCollection;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using Mediator;
|
||||||
|
|
||||||
|
namespace Toolkit.Framework.Foundation;
|
||||||
|
|
||||||
|
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, cancellationToken, handlerCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueTask<TResponse> Handle(TRequest request, CancellationToken cancellationToken) => handler(request, cancellationToken);
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using Mediator;
|
using Mediator;
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace Toolkit.Framework.Foundation;
|
namespace Toolkit.Framework.Foundation;
|
||||||
|
|
||||||
@@ -44,8 +43,7 @@ public class Mediator : IMediator
|
|||||||
|
|
||||||
public ValueTask<TResponse> Send<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken = default)
|
public ValueTask<TResponse> Send<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
dynamic? handler = factory.GetService(typeof(RequestClassHandlerWrapper<,>).MakeGenericType(request.GetType(), typeof(TResponse)));
|
dynamic? handler = factory.GetService(typeof(RequestClassHandlerWrapper<,>).MakeGenericType(request.GetType(), typeof(TResponse)));
|
||||||
|
|
||||||
if (handler is not null)
|
if (handler is not null)
|
||||||
{
|
{
|
||||||
return handler.Handle((dynamic)request, cancellationToken);
|
return handler.Handle((dynamic)request, cancellationToken);
|
||||||
@@ -56,16 +54,70 @@ public class Mediator : IMediator
|
|||||||
|
|
||||||
public ValueTask<TResponse> Send<TResponse>(ICommand<TResponse> command, CancellationToken cancellationToken = default)
|
public ValueTask<TResponse> Send<TResponse>(ICommand<TResponse> command, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
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<TResponse> Send<TResponse>(IQuery<TResponse> query, CancellationToken cancellationToken = default)
|
public ValueTask<TResponse> Send<TResponse>(IQuery<TResponse> query, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
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<object?> Send(object message, CancellationToken cancellationToken = default)
|
public ValueTask<object?> Send(object message, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (message.GetType().GetInterface(typeof(IRequest<>).Name) is { } requestInterface)
|
||||||
|
{
|
||||||
|
if (requestInterface.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 { } commandInterface)
|
||||||
|
{
|
||||||
|
if (commandInterface.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 { } queryInterface)
|
||||||
|
{
|
||||||
|
if (queryInterface.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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using Mediator;
|
||||||
|
|
||||||
|
namespace Toolkit.Framework.Foundation;
|
||||||
|
|
||||||
|
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, cancellationToken, handlerCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.handler = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueTask<TResponse> Handle(TRequest request, CancellationToken cancellationToken) =>
|
||||||
|
handler(request, cancellationToken);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user