代码解耦之道:MediatR在.NET中的实战应用

MediatR是一个强大的工具,可以帮助你构建松耦合、可维护的C#应用程序。通过分离请求和处理程序,它促进了关注点分离,并使得添加新功能和修改现有功能变得更加容易。
首页 新闻资讯 行业资讯 代码解耦之道:MediatR在.NET中的实战应用

1. 引言

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

2. MediatR的核心概念

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

  1. 请求(Request): 表示要执行的操作。

  2. 处理程序(Handler): 负责处理特定类型的请求。

  3. 中介者(Mediator): 协调请求和处理程序之间的通信。

3. 安装MediatR

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

dotnetaddpackage MediatR

4. 基本用法示例

4.1 创建请求和处理程序

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

publicclass GetUserQuery : IRequest<UserDto>{publicintUserId { get;set;}
}publicclass GetUserQueryHandler : IRequestHandler<GetUserQuery,UserDto>{publicasync Task<UserDto>Handle(GetUserQuery request,CancellationToken cancellationToken){// 模拟从数据库获取用户await Task.Delay(100,cancellationToken);// 模拟异步操作returnnew UserDto { Id=request.UserId,Name=$"User {request.UserId}"};}
}publicclass UserDto
{publicintId { get;set;}publicstring Name { get;set;}
}

4.2 配置依赖注入

在Program.cs中配置MediatR:

builder.Services.AddMediatR(cfg=>cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()));
4.3使用MediatR发送请求

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

publicclass UserController : ControllerBase
{
    private readonly IMediator _mediator;publicUserController(IMediator mediator){
        _mediator=mediator;}[HttpGet("{id}")]publicasync Task<ActionResult<UserDto>>GetUser(intid){
        var query=new GetUserQuery { UserId=id };var result=await _mediator.Send(query);returnOk(result);}
}


5. 高级用法示例

5.1 使用通知(Notification)

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

publicclass UserCreatedNotification : INotification
{publicintUserId { get;set;}publicstring UserName { get;set;}
}publicclass EmailNotificationHandler : INotificationHandler<UserCreatedNotification>{publicTask Handle(UserCreatedNotification notification,CancellationToken cancellationToken){
        Console.WriteLine($"Sending email for new user: {notification.UserName}");returnTask.CompletedTask;}
}publicclass LogNotificationHandler : INotificationHandler<UserCreatedNotification>{publicTask Handle(UserCreatedNotification notification,CancellationToken cancellationToken){
        Console.WriteLine($"Logging new user creation: {notification.UserId}");returnTask.CompletedTask;}
}

使用通知:

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

5.2 使用管道行为(Pipeline Behavior)

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

publicclass LoggingBehavior<TRequest,TResponse>: IPipelineBehavior<TRequest,TResponse>{
    private readonly ILogger<LoggingBehavior<TRequest,TResponse>>_logger;publicLoggingBehavior(ILogger<LoggingBehavior<TRequest,TResponse>>logger){
        _logger=logger;}publicasync Task<TResponse>Handle(TRequest request,RequestHandlerDelegate<TResponse>next,CancellationToken cancellationToken){
        _logger.LogInformation($"开始处理请求 {typeof(TRequest).Name}");var response=awaitnext();_logger.LogInformation($"完成处理请求 {typeof(TResponse).Name}");returnresponse;}


}

注册管道行为:

services.AddTransient(typeof(IPipelineBehavior<,>),typeof(LoggingBehavior<,>));
触发:
var query=new GetUserQuery { UserId=1};var result=await _mediator.Send(query);returnOk();


6. 实现请求重试机制

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

publicclass RetryBehavior<TRequest,TResponse>: IPipelineBehavior<TRequest,TResponse>whereTRequest : IRequest<TResponse>{
    private readonly ILogger<RetryBehavior<TRequest,TResponse>>_logger;private constintMaxRetries=3;publicRetryBehavior(ILogger<RetryBehavior<TRequest,TResponse>>logger){
        _logger=logger;}publicasync Task<TResponse>Handle(TRequest request,RequestHandlerDelegate<TResponse>next,CancellationToken cancellationToken){for(inti=0;i<=MaxRetries;i++){
            try
            {if(i>0){
                    _logger.LogWarning($"Retrying {typeof(TRequest).Name} (attempt {i})");}returnawaitnext();}
            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.");}
}
// 在Program.cs中注册builder.Services.AddTransient(typeof(IPipelineBehavior<,>),typeof(RetryBehavior<,>));

7. 最佳实践

  1. 保持请求和处理程序的简单性和单一职责。

  2. 使用通知处理跨切面关注点,如日志记录和事件发布。

  3. 利用管道行为实现横切关注点,如验证、日志记录和性能监控。

  4. 在大型项目中,考虑按功能或模块组织请求和处理程序。

  5. 使用依赖注入容器管理MediatR和其他依赖项。

8. 结论

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

19    2024-09-29 09:58:57    MediatR 工具 程序