namespace GainCapital.Execution.DealingManager.Infrastructure.CqrsExtensions
{
public class CqrsDispatcher : ICqrsDispatcher
{
private static readonly ConcurrentDictionary<Type, QueryDispatcherBase> QueryDispatchers = new ConcurrentDictionary<Type, QueryDispatcherBase>();
private static readonly ConcurrentDictionary<Type, CommandDispatcherBase> CommandDispatchers = new ConcurrentDictionary<Type, CommandDispatcherBase>();
private readonly IServiceProvider _serviceProvider;
private readonly IHttpContextAccessor _httpContextAccessor;
public CqrsDispatcher(IServiceProvider serviceProvider, IHttpContextAccessor httpContextAccessor)
{
_serviceProvider = serviceProvider;
_httpContextAccessor = httpContextAccessor;
}
public Task<TResult> DispatchAsync<TResult>(IQuery<TResult> query)
{
var queryDispatcher = QueryDispatchers.GetOrAdd(query.GetType(), queryType =>
{
var makeGenericType = typeof(QueryDispatcher<,>).MakeGenericType(queryType, typeof(TResult));
return (QueryDispatcherBase)Activator.CreateInstance(makeGenericType)!;
});
var cancellationToken = _httpContextAccessor.HttpContext?.RequestAborted;
return (Task<TResult>)queryDispatcher.Dispatch(query, _serviceProvider, cancellationToken ?? default);
}
public Task<TResult> DispatchAsync<TResult>(ICommand<TResult> command) where TResult : CSharpFunctionalExtensions.IResult
{
var commandDispatcher = CommandDispatchers.GetOrAdd(command.GetType(), commandType =>
{
var makeGenericType = typeof(CommandDispatcher<,>).MakeGenericType(commandType, typeof(TResult));
return (CommandDispatcherBase)Activator.CreateInstance(makeGenericType)!;
});
var cancellationToken = _httpContextAccessor.HttpContext?.RequestAborted;
return (Task<TResult>)commandDispatcher.Dispatch(command, _serviceProvider, cancellationToken ?? default);
}
}
internal abstract class QueryDispatcherBase
{
public abstract object Dispatch(object query, IServiceProvider serviceProvider, CancellationToken cancellationToken);
}
internal class QueryDispatcher<TQuery, TResult> : QueryDispatcherBase where TQuery : IQuery<TResult>
{
public override object Dispatch(object query, IServiceProvider serviceProvider, CancellationToken cancellationToken)
{
return Dispatch((TQuery)query, serviceProvider, cancellationToken);
}
private static async Task<TResult> Dispatch(TQuery query, IServiceProvider serviceProvider, CancellationToken cancellationToken)
{
using var serviceScope = serviceProvider.CreateScope();
var queryHandler = serviceScope.ServiceProvider.GetRequiredService<IQueryHandler<TQuery, TResult>>();
return await queryHandler.Handle(query, cancellationToken);
}
}
internal abstract class CommandDispatcherBase
{
public abstract object Dispatch(object command, IServiceProvider serviceProvider, CancellationToken cancellationToken);
}
internal class CommandDispatcher<TCommand, TResult> : CommandDispatcherBase where TCommand : ICommand<TResult> where TResult : CSharpFunctionalExtensions.IResult
{
public override object Dispatch(object command, IServiceProvider serviceProvider, CancellationToken cancellationToken)
{
return Dispatch((TCommand)command, serviceProvider, cancellationToken);
}
private static async Task<TResult> Dispatch(TCommand command, IServiceProvider serviceProvider, CancellationToken cancellationToken)
{
using var serviceScope = serviceProvider.CreateScope();
var queryHandler = serviceScope.ServiceProvider.GetRequiredService<ICommandHandler<TCommand, TResult>>();
return await queryHandler.HandleAsync(command, cancellationToken);
}
}
}
Paste Hosted With By Wklejamy.pl