using Microsoft.Extensions.DependencyInjection;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
public interface IAggregateRoot
public interface IDbContext
public class Order : IAggregateRoot
public string Name { get; set; }
public interface IQuery<T> : IRequest<T>
Guid CorrelationId { get; }
public abstract class BaseResult
protected BaseResult(ResultStatus status, Dictionary<string, List<string>>? errors)
this.Errors = errors ?? new Dictionary<string, List<string>>();
this.IsSuccess = status == ResultStatus.Success;
public bool IsSuccess { get; private set; }
public ResultStatus Status { get; private set; }
public Dictionary<string, List<string>> Errors { get; private set; }
public class QueryResult<T> : BaseResult
private QueryResult(T? data, ResultStatus status, Dictionary<string, List<string>>? errors)
public static QueryResult<T> Success(T data)
return new QueryResult<T>(data, ResultStatus.Success, null);
public class AggregateRootQuery<TAggregate, TDto>
: IRequest<QueryResult<IEnumerable<TDto>>>, IQuery<IEnumerable<TDto>>
where TAggregate : class, IAggregateRoot
public AggregateRootQuery(Guid correlationId)
this.CorrelationId = correlationId;
public Guid CorrelationId { get; }
public abstract class BaseAggregateRootQueryHandler<TAggregate, TDto> : IRequestHandler<AggregateRootQuery<TAggregate, TDto>, QueryResult<IEnumerable<TDto>>>
where TAggregate : class, IAggregateRoot
protected BaseAggregateRootQueryHandler(
protected IDbContext DbContext { get; }
protected ILogger Logger { get; }
public async Task<QueryResult<IEnumerable<TDto>>> Handle(AggregateRootQuery<TAggregate, TDto> request, CancellationToken cancellationToken)
var entities = new List<TAggregate>();
var dtos = this.MapToDataTransferObjects(entities);
return QueryResult<IEnumerable<TDto>>.Success(dtos);
protected abstract IQueryable<TAggregate> ApplyFilter(IQueryable<TAggregate> source);
protected virtual IEnumerable<TDto> MapToDataTransferObjects(IEnumerable<TAggregate> source)
public class OrderQueryHandler : BaseAggregateRootQueryHandler<Domain.Order, OrderDto>
public OrderQueryHandler(
protected override IQueryable<Domain.Order> ApplyFilter(IQueryable<Domain.Order> source)
return source.OrderBy(x => x.Name);
public class GetSingleExamDetailsOutputDTO
internal class GetSingleExamQuery : IQuery<GetSingleExamDetailsOutputDTO>
public Guid CorrelationId { get; }
public static async Task Main(string[] args)
var services = new ServiceCollection();
services.AddMediatR(configuration =>
configuration.RegisterServicesFromAssembly(typeof(Program).Assembly);
var serviceProvider = services.BuildServiceProvider();
var mediator = serviceProvider.GetRequiredService<IMediator>();
IRequest<QueryResult<IEnumerable<OrderDto>>> query = new AggregateRootQuery<Domain.Order, OrderDto>(Guid.NewGuid());
var result = await mediator.Send(query);
Console.WriteLine(result.GetType());
if (!result.IsSuccess || result.Data == null)