为什么要在.Net Core中使用MediatR library?

本文是翻译,原文:https://medium.com/@dmytrohridin/why-you-need-to-try-mediatr-library-on-your-net-project-653165735c36

MediatR libray 是一款比较优秀的中介者/调停者实现组件,在github上有3000多个星,算是比较成功的组件。最大的特点是基于内存的消息传递,而且不用依赖其他组件。其作者是大名鼎鼎的Jimmy Bogard(AutoMapper的作者)。在这篇文章,我将尝试解释为什么要在我们的项目中引用此组件。

1)更轻的控制器

下面是一种通用的控制器代码实现,相信很多人都写过或见过这样的代码:

 1 public async Task<Response> Create([FromBody] Request request) 
 2 {
 3     var isValid = _validator.Validate(request);
 4     if (!isValid) return _responseBuilder.BuildBadRequest();
 5     
 6     var dto = _mapper.Map<ObjectDto, Request>(request);
 7     
 8     var result = await _repository.Create(dto);
 9     return _responseBuilder.Success(result);
10 }  

 

你可能会想:没啥问题啊?大家不都是这样做的么,先验证,然后映射,最后保存,然后将结果返回给客户,没毛病。

当然,这样做确实没毛病,但是其实我们可以做的更好。

我认为控制器只是一个路由转发,它最好只接受客户的请求,然后让其他handler去处理,结束后将结果再转发给客户。像验证、映射、保存等业务完全可以交由其他的代码去处理,这样才符合标准流程。

 

2)客户质量保证CQS

应用中介者/调停者模式后,不仅允许你对读写进行分离,而且可以对命令和查询进行有效处理,这也是引入MediatR的最大优势。

像我之前提到的,这个组件源于简单中介设计模式,其允许命令、查询和处理程序分离,并降低耦合。

 

3)上代码

你可以在github上面看到详细的代码,https://github.com/dmytrohridin/AspNetCoreMediatRSample, 但是我会对一些关键要点进行解释,以帮助大家如何应用MediatR组件。

 *注:这些代码没有使用任何的分层,只是为什么展示组件用法。

Requests

当你开始使用MediatR组件,第一件事就是什么request,Request描述了你的命令和行为。

1 public class GetOrderQuery : IRequest<Order>
2 {
3     public GetOrderQuery(Guid id)
4     {
5         Id = id;
6     }
7 
8     public Guid Id { get; }
9 }

GetOrderQuery描述了此方法的参数数Id,返回一个实体。所有的请求Request都要继承接口IRequest,这个接口相当于后续给handler处理时的契约。

Handlers

一旦request创建完成,你就可以创建处理程序handler。

 1 public class GetOrderHandler : IRequestHandler<GetOrderQuery, Order>
 2 {
 3     private readonly IOrderRepository orderRepository;
 4 
 5     public GetOrderHandler(IOrderRepository orderRepository)
 6     {
 7         this.orderRepository = orderRepository;
 8     }
 9 
10     public Task<Order> Handle(GetOrderQuery request, CancellationToken cancellationToken)
11     {
12         var result = orderRepository.Get(request.Id);
13         return Task.FromResult(result);
14     }
15 }

所有的Handers都要继承IRequestHandler接口,该接口有两个参数,第一个是输入,第二个是输出。更多的关于request和handlers的描述,在这里https://github.com/jbogard/MediatR/wiki。

现在,我们已经创建好了我们的Query和Handler,该如何使用呢?

 1 public class OrdersController : ControllerBase
 2 {
 3     private readonly IMediator mediator;
 4 
 5     public OrdersController(IMediator mediator) => 
 6         this.mediator = mediator;
 7 
 8     [HttpGet("{id}")]
 9     public async Task<Order> Get(Guid id) => 
10         await mediator.Send(new GetOrderQuery(id));
11 }

你要做的只是定义一个控制器,然后注入mediator,然后发送request,是不是So easy?

妈妈再也不用担心我的代码了。

最后

正如你所看见的,我们通过中介者模式和mediator组件,解耦了request和handlers,并且让controller变得更轻,同时根据符合CQS法则,很赞吧?

这个虽然称不上“银弹”,但是仍然很有用啊!

 

posted on 2019-06-04 14:40  咖啡色  阅读(501)  评论(0编辑  收藏  举报