using AipsCore.Application.Abstract; using AipsCore.Application.Abstract.Command; using AipsCore.Application.Abstract.Query; using Microsoft.Extensions.DependencyInjection; namespace AipsCore.Application.Common.Dispatcher; public sealed class Dispatcher : IDispatcher { private readonly IServiceProvider _serviceProvider; public Dispatcher(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } #region Execute public async Task Execute(ICommand command, CancellationToken cancellationToken = default) { var handlerType = typeof(ICommandHandler<>).MakeGenericType(command.GetType()); await this.Handle(handlerType, command, cancellationToken); } public async Task Execute(ICommand command, CancellationToken cancellationToken = default) { var handlerType = typeof(ICommandHandler<,>).MakeGenericType(command.GetType(), typeof(TResult)); return await this.HandleWithResult(handlerType, command, cancellationToken); } public async Task Execute(IQuery query, CancellationToken cancellationToken = default) { var handlerType = typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TResult)); return await this.HandleWithResult(handlerType, query, cancellationToken); } #endregion #region Handle private async Task Handle(Type handlerType, object commandOrQuery, CancellationToken cancellationToken = default) { dynamic handler = this.ResolveHandler(handlerType, commandOrQuery); await handler.Handle((dynamic)commandOrQuery, cancellationToken); } private async Task HandleWithResult(Type handlerType, object commandOrQuery, CancellationToken cancellationToken = default) { dynamic handler = this.ResolveHandler(handlerType, commandOrQuery); return await handler.Handle((dynamic)commandOrQuery, cancellationToken); } #endregion private dynamic ResolveHandler(Type handlerType, object commandOrQuery) { dynamic? handler = _serviceProvider.GetService(handlerType); if (handler is null) { throw new DispatchException(commandOrQuery); } return handler; } }