Skip to content

快速入门 ​

🚀 从零开始,5分钟上手 MediatR


📦 安装 NuGet 包 ​

基础安装 ​

bash
# 核心包(必需)
dotnet add package MediatR

# ASP.NET Core 依赖注入扩展(推荐)
dotnet add package MediatR.Extensions.Microsoft.DependencyInjection

完整安装(含常用扩展) ​

bash
# 核心包
dotnet add package MediatR

# DI 扩展
dotnet add package MediatR.Extensions.Microsoft.DependencyInjection

# FluentValidation 集成(用于验证)
dotnet add package FluentValidation.AspNetCore
dotnet add package FluentValidation.DependencyInjectionExtensions

# Scrutor(用于装饰器模式)
dotnet add package Scrutor

💻 第一个请求/响应示例 ​

步骤 1:定义请求 ​

csharp
// CreateOrderCommand.cs
using MediatR;

public class CreateOrderCommand : IRequest<OrderResult>
{
    public string ProductName { get; set; }
    public int Quantity { get; set; }
    public decimal Price { get; set; }
}

步骤 2:定义响应 ​

csharp
// OrderResult.cs
public class OrderResult
{
    public Guid OrderId { get; set; }
    public string Status { get; set; }
    public decimal TotalAmount { get; set; }
}

步骤 3:实现处理器 ​

csharp
// CreateOrderHandler.cs
using MediatR;

public class CreateOrderHandler : IRequestHandler<CreateOrderCommand, OrderResult>
{
    public async Task<OrderResult> Handle(CreateOrderCommand request, CancellationToken cancellationToken)
    {
        // 模拟业务逻辑
        var order = new OrderResult
        {
            OrderId = Guid.NewGuid(),
            Status = "Created",
            TotalAmount = request.Quantity * request.Price
        };

        Console.WriteLine($"订单创建成功: {order.OrderId}, 总金额: {order.TotalAmount:C}");
        
        return order;
    }
}

步骤 4:配置 MediatR ​

控制台应用 ​

csharp
// Program.cs
using MediatR;
using Microsoft.Extensions.DependencyInjection;

var services = new ServiceCollection();

// 注册 MediatR
services.AddMediatR(cfg => 
    cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));

var serviceProvider = services.BuildServiceProvider();
var mediator = serviceProvider.GetRequiredService<IMediator>();

// 发送请求
var command = new CreateOrderCommand
{
    ProductName = "iPhone 15 Pro",
    Quantity = 2,
    Price = 7999.00m
};

var result = await mediator.Send(command);

Console.WriteLine($"订单ID: {result.OrderId}");
Console.WriteLine($"状态: {result.Status}");
Console.WriteLine($"总金额: {result.TotalAmount:C}");

输出:

订单创建成功: a3f8b2c1-4d5e-6f7g-8h9i-0j1k2l3m4n5o, 总金额: ¥15,998.00
订单ID: a3f8b2c1-4d5e-6f7g-8h9i-0j1k2l3m4n5o
状态: Created
总金额: ¥15,998.00

🌐 在 ASP.NET Core 中使用 ​

步骤 1:创建 Web API 项目 ​

bash
dotnet new webapi -n MediatR.Demo
cd MediatR.Demo

步骤 2:安装 NuGet 包 ​

bash
dotnet add package MediatR
dotnet add package MediatR.Extensions.Microsoft.DependencyInjection

步骤 3:配置 Program.cs ​

csharp
// Program.cs
using MediatR;

var builder = WebApplication.CreateBuilder(args);

// 添加服务到容器
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

// 注册 MediatR(自动扫描当前程序集)
builder.Services.AddMediatR(cfg => 
    cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));

var app = builder.Build();

// 配置 HTTP 请求管道
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

步骤 4:创建控制器 ​

csharp
// Controllers/OrdersController.cs
using MediatR;
using Microsoft.AspNetCore.Mvc;

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

    public OrdersController(IMediator mediator)
    {
        _mediator = mediator;
    }

    [HttpPost]
    public async Task<ActionResult<OrderResult>> CreateOrder([FromBody] CreateOrderCommand command)
    {
        var result = await _mediator.Send(command);
        return Ok(result);
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<OrderDto>> GetOrder(Guid id)
    {
        var query = new GetOrderQuery { OrderId = id };
        var order = await _mediator.Send(query);
        return Ok(order);
    }
}

步骤 5:运行并测试 ​

bash
dotnet run

访问 Swagger UI:https://localhost:5001/swagger

测试请求:

http
POST https://localhost:5001/api/orders
Content-Type: application/json

{
  "productName": "MacBook Pro",
  "quantity": 1,
  "price": 14999.00
}

响应:

json
{
  "orderId": "a3f8b2c1-4d5e-6f7g-8h9i-0j1k2l3m4n5o",
  "status": "Created",
  "totalAmount": 14999.00
}

🧪 单元测试基础 ​

步骤 1:创建测试项目 ​

bash
dotnet new xunit -n MediatR.Demo.Tests
cd MediatR.Demo.Tests
dotnet add reference ../MediatR.Demo/MediatR.Demo.csproj
dotnet add package Moq

步骤 2:编写测试 ​

csharp
// CreateOrderHandlerTests.cs
using Xunit;
using Moq;

public class CreateOrderHandlerTests
{
    private readonly CreateOrderHandler _handler;

    public CreateOrderHandlerTests()
    {
        _handler = new CreateOrderHandler();
    }

    [Fact]
    public async Task Handle_ValidCommand_ShouldCreateOrder()
    {
        // Arrange
        var command = new CreateOrderCommand
        {
            ProductName = "Test Product",
            Quantity = 5,
            Price = 100.00m
        };

        // Act
        var result = await _handler.Handle(command, CancellationToken.None);

        // Assert
        Assert.NotNull(result);
        Assert.NotEqual(Guid.Empty, result.OrderId);
        Assert.Equal("Created", result.Status);
        Assert.Equal(500.00m, result.TotalAmount);
    }

    [Theory]
    [InlineData("Product A", 1, 50.00, 50.00)]
    [InlineData("Product B", 3, 100.00, 300.00)]
    [InlineData("Product C", 10, 25.50, 255.00)]
    public async Task Handle_DifferentQuantities_ShouldCalculateCorrectTotal(
        string productName, int quantity, decimal price, decimal expectedTotal)
    {
        // Arrange
        var command = new CreateOrderCommand
        {
            ProductName = productName,
            Quantity = quantity,
            Price = price
        };

        // Act
        var result = await _handler.Handle(command, CancellationToken.None);

        // Assert
        Assert.Equal(expectedTotal, result.TotalAmount);
    }
}

步骤 3:运行测试 ​

bash
dotnet test

输出:

Passed!  - Failed:     0, Passed:     4, Skipped:     0, Total:     4

🔧 常见配置选项 ​

1. 多程序集扫描 ​

csharp
// 当 Handler 分布在多个程序集时
builder.Services.AddMediatR(cfg => {
    cfg.RegisterServicesFromAssembly(typeof(Program).Assembly);
    cfg.RegisterServicesFromAssembly(typeof(SharedLibraryMarker).Assembly);
    cfg.RegisterServicesFromAssembly(typeof(OrderHandlersMarker).Assembly);
});

2. 自定义服务生命周期 ​

csharp
// 默认是 Transient,可以自定义
builder.Services.AddMediatR(cfg => {
    cfg.RegisterServicesFromAssembly(typeof(Program).Assembly);
    cfg.Lifetime = ServiceLifetime.Scoped; // 改为 Scoped
});

3. 禁用行为注册 ​

csharp
// 如果不使用任何管道行为,可以禁用自动注册
builder.Services.AddMediatR(cfg => {
    cfg.RegisterServicesFromAssembly(typeof(Program).Assembly);
    cfg.AutoRegisterRequestProcessors = false;
});

📝 完整示例:待办事项应用 ​

项目结构 ​

TodoApp/
├── Models/
│   ├── TodoItem.cs
│   └── TodoResult.cs
├── Commands/
│   ├── CreateTodoCommand.cs
│   └── CreateTodoHandler.cs
├── Queries/
│   ├── GetTodosQuery.cs
│   └── GetTodosHandler.cs
├── Controllers/
│   └── TodosController.cs
└── Program.cs

代码实现 ​

模型 ​

csharp
// Models/TodoItem.cs
public class TodoItem
{
    public Guid Id { get; set; }
    public string Title { get; set; }
    public bool IsCompleted { get; set; }
    public DateTime CreatedAt { get; set; }
}

// Models/TodoResult.cs
public class TodoResult
{
    public Guid Id { get; set; }
    public string Message { get; set; }
}

命令和处理器 ​

csharp
// Commands/CreateTodoCommand.cs
public class CreateTodoCommand : IRequest<TodoResult>
{
    public string Title { get; set; }
}

// Commands/CreateTodoHandler.cs
public class CreateTodoHandler : IRequestHandler<CreateTodoCommand, TodoResult>
{
    private static readonly List<TodoItem> _todos = new();

    public Task<TodoResult> Handle(CreateTodoCommand request, CancellationToken ct)
    {
        var todo = new TodoItem
        {
            Id = Guid.NewGuid(),
            Title = request.Title,
            IsCompleted = false,
            CreatedAt = DateTime.UtcNow
        };

        _todos.Add(todo);

        return Task.FromResult(new TodoResult
        {
            Id = todo.Id,
            Message = $"待办事项 '{request.Title}' 创建成功"
        });
    }
}

查询和处理器 ​

csharp
// Queries/GetTodosQuery.cs
public class GetTodosQuery : IRequest<List<TodoItem>>
{
}

// Queries/GetTodosHandler.cs
public class GetTodosHandler : IRequestHandler<GetTodosQuery, List<TodoItem>>
{
    private static readonly List<TodoItem> _todos = new();

    public Task<List<TodoItem>> Handle(GetTodosQuery request, CancellationToken ct)
    {
        return Task.FromResult(_todos.ToList());
    }
}

控制器 ​

csharp
// Controllers/TodosController.cs
[ApiController]
[Route("api/[controller]")]
public class TodosController : ControllerBase
{
    private readonly IMediator _mediator;

    public TodosController(IMediator mediator)
    {
        _mediator = mediator;
    }

    [HttpPost]
    public async Task<ActionResult<TodoResult>> CreateTodo([FromBody] CreateTodoCommand command)
    {
        var result = await _mediator.Send(command);
        return Ok(result);
    }

    [HttpGet]
    public async Task<ActionResult<List<TodoItem>>> GetTodos()
    {
        var todos = await _mediator.Send(new GetTodosQuery());
        return Ok(todos);
    }
}

测试 ​

bash
# 创建待办事项
curl -X POST https://localhost:5001/api/todos \
  -H "Content-Type: application/json" \
  -d '{"title":"学习 MediatR"}'

# 获取所有待办事项
curl https://localhost:5001/api/todos

⚡ 快速上手检查清单 ​

完成以下步骤,确认你已经掌握了基础:

  • [ ] 安装了 MediatR NuGet 包
  • [ ] 创建了第一个请求(IRequest)
  • [ ] 实现了第一个处理器(IRequestHandler)
  • [ ] 在程序中配置了 MediatR
  • [ ] 成功发送了请求并接收到响应
  • [ ] 理解了 IMediator.Send() 的作用
  • [ ] 编写了一个简单的单元测试
  • [ ] 在 ASP.NET Core 项目中集成了 MediatR

🎯 下一步 ​

恭喜!你已经完成了 MediatR 的快速入门。接下来深入学习:

  1. 核心概念 - 深入理解 IRequest、IRequestHandler、IMediator 等核心 API
  2. 管道行为 - 学习如何实现日志、验证、事务等横切关注点
  3. 通知机制 - 掌握发布/订阅模式

📚 参考资源 ​


💡 提示:动手实践是学习 MediatR 最快的方式。尝试修改上面的示例代码,添加自己的业务逻辑,观察运行结果。

Released under the CC BY-SA 4.0 License.