.NET 轻量级 中介者模式实现库MediatR使用示例

什么是 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) 场景。

评论