OnionArch - 采用DDD+CQRS+.Net 7.0实现的洋葱架构( 三 )

8.GRPC Message做为业务用例实体通过将GRPC proto文件放入Application项目,重用其生成的message作为业务用例实体(Model) 。
public class AddCategoryCommand : ICommand{public AddCategoryRequest Model { get; set; }}其中AddCategoryRequest 为proto生成的message 。
9.通用CURD业务用例在应用层分别实现了CURD的Command(增改删)和Query(查询) Handler 。

OnionArch - 采用DDD+CQRS+.Net 7.0实现的洋葱架构

文章插图
OnionArch - 采用DDD+CQRS+.Net 7.0实现的洋葱架构

文章插图
public class CUDCommandHandler<TModel, TEntity> : IRequestHandler<CUDCommand<TModel>> where TEntity : BaseEntity{private readonly CURDDomainService<TEntity> _curdDomainService;public CUDCommandHandler(CURDDomainService<TEntity> curdDomainService){_curdDomainService = curdDomainService;}public async Task<Unit> Handle(CUDCommand<TModel> request, CancellationToken cancellationToken){TEntity entity = null;if (request.Operation == "C" || request.Operation == "U"){if (request.Model == null){throw new BadRequestException($"the model of this request is null");}entity = request.Model.Adapt<TEntity>();if (entity == null){throw new ArgumentNullException($"the entity of {nameof(TEntity)} is null");}}if (request.Operation == "U" || request.Operation == "D"){if (request.Id == Guid.Empty){throw new BadRequestException($"the Id of this request is null");}}switch (request.Operation){case "C":await _curdDomainService.Create(entity);break;case "U":await _curdDomainService.Update(entity);break;case "D":await _curdDomainService.Delete(request.Id);break;}return Unit.Value;}}开发人员只需要在GRPC层简单调用即可实现CURD业务 。
public async override Task<AddProductReply> AddProduct(AddProductRequest request, ServerCallContext context){CUDCommand<AddProductRequest> addProductCommand = new CUDCommand<AddProductRequest>();addProductCommand.Id = Guid.NewGuid();addProductCommand.Model = request;addProductCommand.Operation = "C";await _mediator.Send(addProductCommand);return new AddProductReply(){Message = "Add Product sucess"};}10. 业务实体验证通过FluentValidation和MediatR 管道实现业务实体自动验证,并自动抛出自定义异常 。
OnionArch - 采用DDD+CQRS+.Net 7.0实现的洋葱架构

文章插图
OnionArch - 采用DDD+CQRS+.Net 7.0实现的洋葱架构

文章插图
public class RequestValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>{private readonly IEnumerable<IValidator<TRequest>> _validators;public RequestValidationBehavior(IEnumerable<IValidator<TRequest>> validators){_validators = validators;}public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next){var errors = _validators.Select(v => v.Validate(request)).SelectMany(result => result.Errors).Where(error => error != null).ToList();if (errors.Any()){var errorBuilder = new StringBuilder();errorBuilder.AppendLine("Invalid Request, reason: ");foreach (var error in errors){errorBuilder.AppendLine(error.ErrorMessage);}throw new InvalidRequestException(errorBuilder.ToString(), null);}return await next();}}开发人员只需要定义验证规则即可
public class AddCategoryCommandValidator : AbstractValidator<AddCategoryCommand>{public AddCategoryCommandValidator(){RuleFor(x => x.Model.CategoryName).NotEmpty().WithMessage(p => "类别名称不能为空.");}}11.请求日志和性能日志记录基于MediatR 管道实现请求日志和性能日志记录 。

推荐阅读