c# - 如何避免 MediatR 请求处理程序中的代码重复?

标签 c# oop domain-driven-design cqrs mediatr

我正在研究 CQRS 和 MediatR 库,试图学习一些最佳实践。 我遇到的一个问题是命令/查询处理程序中的代码重复。我想知道在处理程序之间共享逻辑的最佳方式是什么。

例子: 我有一个定义 ID 属性的抽象实体类。所有实体都继承自该类。

public abstract class Entity
{
    public long Id { get; private set; }

    protected Entity(long id)
    {
        Id = id;
    }
    ...
}

然后,我想为每个实体创建一个 GetById 查询。其中一个查询如下所示:

public class GetUserByIdQuery : IRequest<UserDto>
{
    public long UserId { get; set; }
    public class Handler : IRequestHandler<GetUserByIdQuery, UserDto>
    {
        private readonly IRepository<User> repository;
        private readonly IMapper mapper;

        public Handler(IUnitOfWork unitOfWork, IMapper mapper)
        {
            repository = unitOfWork.GetRepository<User>();
            this.mapper = mapper;
        }
        public async Task<UserDto> Handle(GetUserByIdQuery request, CancellationToken cancellationToken)
        {
            var user = await repository.FindAsync(request.UserId, null, cancellationToken);
            if (user is null)
            {
                throw new EntityNotFoundException();
            }

            return mapper.Map<UserDto>(user);
        }
    }

}

问题是这个类对于所有实体来说看起来完全一样。如果没有 CQRS,我可能会有这样的事情:

public class EntityFinder<TEntity, TDto> where TEntity : Entity
{
    private readonly IRepository<TEntity> repository;
    private readonly IMapper mapper;

    public EntityFinder(IUnitOfWork unitOfWork, IMapper mapper)
    {
        repository = unitOfWork.GetRepository<TEntity>();
        this.mapper = mapper;
    }
    public async Task<TDto> GetByIdAsync(long id)
    {
        var entity = await repository.FindAsync(id);
        if (entity is null)
        {
            throw new EntityNotFoundException();
        }

        return mapper.Map<TDto>(entity);
    }
}

我尝试用通用查询和处理程序做类似的事情,但 MediatR 找不到处理程序(即使我尝试手动将其注册到 DI 容器)。

避免此类重复的最佳方法是什么?

最佳答案

你能试试下面的代码吗?这样,您可以重用加载代码,同时提供一个端点来处理请求。

public class EntityFinder<TEntity, TDto> where TEntity : Entity
{ ... // Same as your code }

public class GetUserByIdQuery : IRequest<UserDto>
{
    public long UserId { get; set; }
    public class Handler : IRequestHandler<GetUserByIdQuery, UserDto>, EntityFinder<User, UserDto>
    {
        public Handler(IUnitOfWork unitOfWork, IMapper mapper) : base(unitOfWork, mapper)
        { }
        public async Task<UserDto> Handle(GetUserByIdQuery request, CancellationToken cancellationToken)
            => await base.GetByIdAsync(request.UserId);
    }

}

关于c# - 如何避免 MediatR 请求处理程序中的代码重复?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60552929/

相关文章:

c# - 做编译绑定(bind)(x :Bind) require the ViewModel to derive from DependencyObject?

php - 在MVC中应该如何构建模型?

javascript - 检查 jQuery .hover 操作是否已绑定(bind)

c# - 如何在 C# 中创建字典树

c# - 使用 LINQ 或 XPATH 将 xml 节点的后代作为 List<string> 返回

python - 重载运算符 __mul__ python

oop - 域模型中的继承与枚举属性

web-services - 如何在 DDD 中处理外部有状态的 Web 服务?

language-agnostic - DDD : can a repository return boolean values?

c# - 防火墙后的 WCF 服务——如何设置端口转发?