Stay Hungry,Stay Foolish!

Introduction to MediaTr

Introduction to MediaTr

https://jdaniel1987.github.io/MediaTr

 

这是一篇基于你提供的网页内容整理、润色后的技术博客文章。文章优化了结构,补充了完整的代码逻辑,并增加了 Mermaid 架构图来直观展示 MediatR 的工作原理。


🚀 解锁 .NET 架构之力:MediatR 深度解析与实战指南

随着应用程序规模的不断扩大,你是否发现代码越来越难以维护?尤其是当组件之间存在紧密耦合时,修改一处往往牵一发而动全身。

这就是 MediatR 大显身手的地方。作为一个简单高效的 .NET 库,MediatR 实现了中介者模式,通过解耦复杂的业务逻辑,帮助开发者构建更具可维护性、可扩展性和可测试性的代码。

本文将带你深入了解 MediatR 的核心优势,并通过完整的代码示例,教你如何在 .NET 项目中从零开始集成它。


💡 为什么选择 MediatR?

MediatR 允许你在应用程序的不同部分之间分发命令、查询和事件,而无需让它们直接相互了解。这种“中间人”机制带来了以下显著优势:

  • 松耦合: 组件通过中介者通信,无需了解对方的内部结构。
  • 关注点分离: 将调度逻辑与业务逻辑分离,代码职责更清晰。
  • 可扩展性: 添加新的处理器非常简单,每个处理器只负责单一职责。
  • 易于测试: 处理器相互隔离,Mock 和单元测试变得轻而易举。
  • 代码整洁: 极大地减少了控制器构造函数中的服务注入,告别“构造函数地狱”。

🏗️ 核心架构:它是如何工作的?

在深入代码之前,让我们通过架构图来理解 MediatR 的工作流。它就像一个邮局:发送者(Sender)把信件(Request)投递给邮局(Mediator),邮局负责将其分发给唯一的收件人(Handler)。

sequenceDiagram
    participant Client as 客户端 (Controller/API)
    participant Mediator as 中介者 (IMediator)
    participant Handler as 处理器 (RequestHandler)
    participant Service as 业务服务/数据库

    Client->>Mediator: 发送请求 (Send Request)
    Mediator->>Handler: 路由到对应的处理器
    Handler->>Service: 执行具体业务逻辑
    Service-->>Handler: 返回结果
    Handler-->>Mediator: 处理完成
    Mediator-->>Client: 返回最终响应

🛠️ 实战演练:5步集成 MediatR

下面我们将通过一个“创建用户”的场景,演示如何在 .NET 项目中完整地使用 MediatR。

1. 安装 NuGet 包

首先,你需要安装核心库以及依赖注入扩展包。在 NuGet 包管理器中搜索并安装:

  • MediatR
  • MediatR.Extensions.Microsoft.DependencyInjection

2. 定义请求与处理器

这是 MediatR 的核心。我们需要定义一个请求对象(Request)和一个对应的处理器(Handler)。

场景: 接收用户创建请求,并返回创建好的用户对象。

using MediatR;

// 1. 定义请求对象 (Request)
// 实现 IRequest<TResponse> 表示这是一个需要返回结果的请求
public class CreateUserRequest : IRequest<User>
{
    public string Name { get; set; }
    public string Email { get; set; }
}

// 假设的用户实体
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
}

// 2. 定义处理器 (Handler)
// 实现 IRequestHandler<TRequest, TResponse>
public class CreateUserRequestHandler : IRequestHandler<CreateUserRequest, User>
{
    // 如果有数据库上下文或其他服务,可以通过构造函数注入
    // private readonly AppDbContext _context;
    // public CreateUserRequestHandler(AppDbContext context) { _context = context; }

    public async Task<User> Handle(CreateUserRequest request, CancellationToken cancellationToken)
    {
        // 模拟业务逻辑:创建用户
        var user = new User
        {
            Id = 1, // 实际场景中通常由数据库生成
            Name = request.Name,
            Email = request.Email
        };

        // 模拟异步操作,例如 _context.SaveChangesAsync()
        await Task.Delay(1, cancellationToken);

        return user;
    }
}

3. 注册 MediatR 服务

在 .NET 6+ 的 Program.cs 文件中,将 MediatR 注册到依赖注入容器中。

using MediatR;
using System.Reflection;

var builder = WebApplication.CreateBuilder(args);

// 注册 MediatR
// 注意:需要传入包含 Handler 的程序集,通常是当前项目的 Assembly
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()));

// 其他服务注册...
builder.Services.AddControllers();

var app = builder.Build();

app.MapControllers();
app.Run();

4. 在控制器或 Minimal API 中使用

现在,控制器不再需要注入具体的业务服务,只需要注入 IMediator

方式 A:在传统 Controller 中使用

using Microsoft.AspNetCore.Mvc;
using MediatR;

[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    private readonly IMediator _mediator;

    // 仅注入 IMediator,实现了解耦
    public UsersController(IMediator mediator)
    {
        _mediator = mediator;
    }

    [HttpPost]
    public async Task<IActionResult> CreateUser([FromBody] CreateUserRequest request)
    {
        // "魔法"发生在这里:发送请求,MediatR 会自动找到对应的 Handler
        var user = await _mediator.Send(request);
        
        return CreatedAtAction(nameof(GetUser), new { id = user.Id }, user);
    }
    
    // 假设的 GetUser 方法用于 CreatedAtAction
    [HttpGet("{id}")]
    public IActionResult GetUser(int id) => Ok(new User { Id = id });
}

方式 B:在 Minimal API 中使用

如果你使用的是 .NET 7/8 的 Minimal API,代码会更加简洁:

app.MapPost("/api/users", async (IMediator mediator, CreateUserRequest request) =>
{
    var user = await mediator.Send(request);
    return Results.Created($"/api/users/{user.Id}", user);
})
.WithName("CreateUser")
.WithOpenApi();

5. 进阶:使用通知与事件

MediatR 不仅支持请求/响应模式,还支持发布/订阅模式(通知)。这对于解耦副作用操作(如发送邮件、记录日志)非常有用。

场景: 用户创建成功后,发布一个通知,后台记录日志。

// 1. 定义通知 (Notification)
public class UserCreatedNotification : INotification
{
    public User User { get; set; }
}

// 2. 定义通知处理器 (Notification Handler)
// 注意:通知可以有多个处理器,它们都会被执行
public class UserCreatedNotificationHandler : INotificationHandler<UserCreatedNotification>
{
    public Task Handle(UserCreatedNotification notification, CancellationToken cancellationToken)
    {
        // 执行副作用逻辑,例如发送邮件或写日志
        Console.WriteLine($"[通知] 新用户已创建:{notification.User.Name} ({notification.User.Email})");
        
        return Task.CompletedTask;
    }
}

如何触发?
你可以在 CreateUserRequestHandlerHandle 方法末尾注入 IMediator 并调用 Publish

// 在 CreateUserRequestHandler 内部
await _mediator.Publish(new UserCreatedNotification { User = user });

📌 总结

通过引入 MediatR,我们成功地将业务逻辑从控制器中剥离出来,实现了清晰的关注点分离

  • 控制器只负责处理 HTTP 请求和响应。
  • 处理器只负责具体的业务逻辑。
  • MediatR 负责它们之间的通信。

这种架构模式不仅让代码更加整洁,也为未来的功能扩展和单元测试打下了坚实的基础。希望这篇指南能帮助你更好地组织 .NET 项目架构!

posted @ 2026-08-27 16:07  lightsong  阅读(3)  评论(0)    收藏  举报
千山鸟飞绝,万径人踪灭