快速入门
🚀 从零开始,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 的快速入门。接下来深入学习:
📚 参考资源
- 官方示例: https://github.com/jbogard/MediatR/tree/master/samples
- API 文档: https://github.com/jbogard/MediatR/wiki
- 常见问题: 常见问题与解决方案
💡 提示:动手实践是学习 MediatR 最快的方式。尝试修改上面的示例代码,添加自己的业务逻辑,观察运行结果。