什么是 MediatR?
MediatR 是一个 .NET 生态中的轻量级 中介者模式(Mediator Pattern) 实现库,由 Jimmy Bogard 开发。它的主要目标是减少对象之间的直接依赖,增强应用程序的解耦性、可维护性和可测试性。MediatR 通过请求-响应模式来协调命令、查询和通知,从而实现模块间的松耦合。
MediatR 的核心概念
请求(Request)和处理器(Handler)
在 MediatR 中,所有的业务逻辑操作都是通过请求(Request)来触发,并由对应的处理器(Handler)执行。这种方式可以有效解耦调用方与处理方,使代码更易维护。
命令(Command)和查询(Query)
命令(Command):用于执行具有副作用的操作,例如创建、更新、删除数据。
查询(Query):用于获取数据,不会修改系统状态,例如获取用户信息或订单详情。
通知(Notification)
通知允许一个事件被多个处理器处理,适用于事件驱动架构(EDA)。当某个事件发生时,可以触发多个处理逻辑,而不需要事件源与处理逻辑之间建立直接引用。
管道行为(Pipeline Behavior)
MediatR 支持管道行为(Pipeline Behavior),类似于 ASP.NET Core 的中间件,可以用于日志记录、事务管理、性能监控、身份验证等操作。
MediatR 代码示例
安装 MediatR
在 .NET 项目中安装 MediatR 及其依赖:
dotnet add package MediatR
dotnet add package MediatR.Extensions.Microsoft.DependencyInjection
创建 Command(命令)和 Query(查询)
Command(创建用户命令)
using MediatR;
public record CreateUserCommand(string Name, int Age) : IRequest<User>;
这里的 CreateUserCommand 继承自 IRequest<User>,表示该请求会返回一个 User 对象。
Query(获取用户查询)
using MediatR;
public record GetUserQuery(int Id) : IRequest<User>;
这里的 GetUserQuery 继承自 IRequest<User>,表示查询用户的请求会返回 User 对象。
创建请求处理器(Handler)
处理 Command
using MediatR;
using System.Threading;
using System.Threading.Tasks;
public class CreateUserHandler : IRequestHandler<CreateUserCommand, User>
{
public async Task<User> Handle(CreateUserCommand request, CancellationToken cancellationToken)
{
// 模拟数据库操作
var user = new User { Id = new Random().Next(1, 1000), Name = request.Name, Age = request.Age };
return await Task.FromResult(user);
}
}
处理 Query
using MediatR;
using System.Threading;
using System.Threading.Tasks;
public class GetUserHandler : IRequestHandler<GetUserQuery, User>
{
public async Task<User> Handle(GetUserQuery request, CancellationToken cancellationToken)
{
// 模拟查询数据库
var user = new User { Id = request.Id, Name = "Test User", Age = 25 };
return await Task.FromResult(user);
}
}
通知(Notification)模式
通知适用于 事件驱动架构(EDA),允许一个事件触发多个处理逻辑。
定义通知(Notification)
using MediatR;
public record UserCreatedNotification(int UserId) : INotification;
创建通知处理器(Handler)
using MediatR;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
public class UserCreatedHandler1 : INotificationHandler<UserCreatedNotification>
{
public Task Handle(UserCreatedNotification notification, CancellationToken cancellationToken)
{
Debug.WriteLine($"Handler1: User with ID {notification.UserId} was created.");
return Task.CompletedTask;
}
}
public class UserCreatedHandler2 : INotificationHandler<UserCreatedNotification>
{
public Task Handle(UserCreatedNotification notification, CancellationToken cancellationToken)
{
Debug.WriteLine($"Handler2: Sending welcome email to user ID {notification.UserId}.");
return Task.CompletedTask;
}
}
管道行为(Pipeline Behavior)
管道行为类似于 ASP.NET Core 中间件,可用于日志记录、事务管理、身份验证等。
创建管道行为
using MediatR;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
{
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
{
Debug.WriteLine($"Handling {typeof(TRequest).Name}");
var response = await next();
Debug.WriteLine($"Handled {typeof(TResponse).Name}");
return response;
}
}
在 Program.cs 中注册:
builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
配置 MediatR 并集成 ASP.NET Core
在 Program.cs(.NET 6/7/8)中注册 MediatR:
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
var builder = WebApplication.CreateBuilder(args);
// 注册 MediatR
builder.Services.AddMediatR(Assembly.GetExecutingAssembly());
var app = builder.Build();
app.MapGet("/", () => "MediatR API is running!");
app.Run();
在 API 控制器中使用 MediatR
using MediatR;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
[ApiController]
[Route("api/users")]
public class UsersController : ControllerBase
{
private readonly IMediator _mediator;
public UsersController(IMediator mediator)
{
_mediator = mediator;
}
[HttpPost]
public async Task<IActionResult> CreateUser([FromBody] CreateUserCommand command)
{
var user = await _mediator.Send(command);
await _mediator.Publish(new UserCreatedNotification(user.Id));
return Ok(user);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetUser(int id)
{
var user = await _mediator.Send(new GetUserQuery(id));
return Ok(user);
}
}
MediatR 的使用场景
CQRS(命令查询职责分离)架构:MediatR 非常适合实现 CQRS,将查询与命令逻辑分离,提高系统扩展性。
解耦业务逻辑:通过中介者模式,避免直接依赖多个服务,降低代码耦合度。
事件驱动架构:可以使用通知机制在应用程序中传播事件,增强可扩展性。
日志和性能监控:利用管道行为(Pipeline Behavior)在请求执行前后添加日志、监控、验证等功能。
MediatR 作为 .NET 生态中优秀的中介者模式实现,极大地提升了代码的可读性、可维护性和可测试性。它特别适用于希望降低依赖、提升架构灵活性的 .NET 应用程序,如 ASP.NET Core Web API、微服务架构和领域驱动设计(DDD) 场景。