前言
ASP.NET Core
的 Middleware
(中间件)使用了管道模式:

Request
(请求)在管道中传递,依次经过管道中的每一个 MiddleWare
进行处理。
MiddleWare
就像一层层的“滤网”,过滤所有的请求和响应。
这种模式的好处在于,分离关注点。比如验证用户、记录访问日志,可以将这些任务分解到不同 MiddleWare
中,互相解耦。
既然 ASP.NET Core
已经实现了管道模式,为什么还要在业务层实现一遍呢?
原因
我觉得可以分为 2 方面考虑:
- 与顶级框架解耦,不能保证应用程序代码始终运行在
ASP.NET Core
下,如果将业务迁移到 WPF
,记录访问日志这类放在管道中的功能还是需要实现
- 同时支持不同来源请求,请求可能来自于
Web API
,也可能来自于 Windows Service
定时调用,但业务层处理逻辑应保持一样
因此,ASP.NET Core
框架应该只用于接收输入和返回输出,而在业务层实现管道模式。
定义 API 的最佳实践
这里使用了 MediatR
类库实现 Controller
方法,将业务逻辑和 Controller
进行隔离。
示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
[HttpGet]
public async Task<string> Demo([FromQuery] DemoQuery request)
{
return await _mediator.Send(request);
}
public class DemoQuery : IRequest<string>
{
public string Name { get; set; }
}
public class DemoQueryHandler : IRequestHandler<DemoQuery, string>
{
public async Task<string> Handle(DemoQuery request, CancellationToken cancellationToken)
{
Console.WriteLine("DemoQueryHandler执行");
return request.Name;
}
}
|
而 MediatR
不仅仅是一个简单的中介模式实现,它还提供了 Behaviors
的概念。

Behaviors
非常类似于 ASP.NET Core
中的 MiddleWare
,可以让我们实现管道模式。
管道实现
要定义 Behaviors
,我们需要实现 IPipelineBehavior
接口,示例代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public class FirstPipelineBehavior<TRequest, TResponse>
: IPipelineBehavior<TRequest, TResponse>
{
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
Console.WriteLine("FirstPipelineBehavior执行中");
var response = await next();
Console.WriteLine("FirstPipelineBehavior执行完成");
return response;
}
}
|
和 MiddleWare
类似,调用 next()
可以将请求向下传递。
接着在 Startup.cs
中注册管道:
1
2
3
4
|
services.AddMediatR(typeof(Startup));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(FirstPipelineBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(SecondPipelineBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ThirdPipelineBehavior<,>));
|
访问 API
可以看到,管道可以在 IRequestHandler
执行之前和之后执行代码,并且处理顺序和注册顺序相同:
