编辑
2025-02-05
C# 应用
00
请注意,本文编写于 90 天前,最后修改于 90 天前,其中某些信息可能已经过时。

目录

引言
MediatR的核心概念
安装MediatR
基本用法示例
创建请求和处理程序
配置依赖注入
使用MediatR发送请求
高级用法示例
使用通知(Notification)
使用管道行为(Pipeline Behavior)
实现请求重试机制
最佳实践
结论

引言

MediatR是一个轻量级的中介者模式实现库,用于在.NET应用程序中处理进程内消息传递。它有助于降低代码耦合度,提高可维护性和可测试性。本文将深入探讨MediatR的使用方法,并提供多个实际示例。

MediatR的核心概念

在深入示例之前,让我们先了解MediatR的几个核心概念:

  1. 请求(Request): 表示要执行的操作。
  2. 处理程序(Handler): 负责处理特定类型的请求。
  3. 中介者(Mediator): 协调请求和处理程序之间的通信。

安装MediatR

首先,通过NuGet包管理器安装MediatR:

Markdown
dotnet add package MediatR

image.png

基本用法示例

创建请求和处理程序

让我们从一个简单的示例开始,创建一个获取用户信息的请求:

C#
public class GetUserQuery : IRequest<UserDto> { public int UserId { get; set; } } public class GetUserQueryHandler : IRequestHandler<GetUserQuery, UserDto> { public async Task<UserDto> Handle(GetUserQuery request, CancellationToken cancellationToken) { // 模拟从数据库获取用户 await Task.Delay(100, cancellationToken); // 模拟异步操作 return new UserDto { Id = request.UserId, Name = $"User {request.UserId}" }; } } public class UserDto { public int Id { get; set; } public string Name { get; set; } }

配置依赖注入

Program.cs中配置MediatR:

C#
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()));

使用MediatR发送请求

在控制器或服务中使用MediatR:

C#
public class UserController : ControllerBase { private readonly IMediator _mediator; public UserController(IMediator mediator) { _mediator = mediator; } [HttpGet("{id}")] public async Task<ActionResult<UserDto>> GetUser(int id) { var query = new GetUserQuery { UserId = id }; var result = await _mediator.Send(query); return Ok(result); } }

image.png

高级用法示例

使用通知(Notification)

通知允许多个处理程序响应同一个事件:

C#
public class UserCreatedNotification : INotification { public int UserId { get; set; } public string UserName { get; set; } } public class EmailNotificationHandler : INotificationHandler<UserCreatedNotification> { public Task Handle(UserCreatedNotification notification, CancellationToken cancellationToken) { Console.WriteLine($"Sending email for new user: {notification.UserName}"); return Task.CompletedTask; } } public class LogNotificationHandler : INotificationHandler<UserCreatedNotification> { public Task Handle(UserCreatedNotification notification, CancellationToken cancellationToken) { Console.WriteLine($"Logging new user creation: {notification.UserId}"); return Task.CompletedTask; } }

使用通知:

C#
await _mediator.Publish(new UserCreatedNotification { UserId = 1, UserName = "John Doe" });

image.png

使用管道行为(Pipeline Behavior)

管道行为允许你在处理请求之前和之后执行代码:

C#
public class LoggingBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> { private readonly ILogger<LoggingBehavior<TRequest, TResponse>> _logger; public LoggingBehavior(ILogger<LoggingBehavior<TRequest, TResponse>> logger) { _logger = logger; } public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next,CancellationToken cancellationToken) { _logger.LogInformation($"开始处理请求 {typeof(TRequest).Name}"); var response = await next(); _logger.LogInformation($"完成处理请求 {typeof(TResponse).Name}"); return response; } }

注册管道行为:

C#
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));

触发:

C#
var query = new GetUserQuery { UserId = 1 }; var result = await _mediator.Send(query); return Ok();

image.png

实现请求重试机制

创建一个行为来自动重试失败的请求:

C#
public class RetryBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse> { private readonly ILogger<RetryBehavior<TRequest, TResponse>> _logger; private const int MaxRetries = 3; public RetryBehavior(ILogger<RetryBehavior<TRequest, TResponse>> logger) { _logger = logger; } public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken) { for (int i = 0; i <= MaxRetries; i++) { try { if (i > 0) { _logger.LogWarning($"Retrying {typeof(TRequest).Name} (attempt {i})"); } return await next(); } catch (Exception ex) when (i < MaxRetries) { _logger.LogError(ex, $"Error handling {typeof(TRequest).Name}. Retry attempt {i + 1} of {MaxRetries}"); await Task.Delay(1000 * i, cancellationToken); } } throw new Exception($"Failed to process {typeof(TRequest).Name} after {MaxRetries} retries."); } }
C#
// 在Program.cs中注册 builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RetryBehavior<,>));

最佳实践

  1. 保持请求和处理程序的简单性和单一职责。
  2. 使用通知处理跨切面关注点,如日志记录和事件发布。
  3. 利用管道行为实现横切关注点,如验证、日志记录和性能监控。
  4. 在大型项目中,考虑按功能或模块组织请求和处理程序。
  5. 使用依赖注入容器管理MediatR和其他依赖项。

结论

MediatR是一个强大的工具,可以帮助你构建松耦合、可维护的C#应用程序。通过分离请求和处理程序,它促进了关注点分离,并使得添加新功能和修改现有功能变得更加容易。结合CQRS模式,MediatR可以成为构建可扩展和高性能应用程序的有力工具。

本文作者:rick

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!