首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >MediatR:从青铜到王者,解锁.NET消息处理终极奥义!

MediatR:从青铜到王者,解锁.NET消息处理终极奥义!

作者头像
云中小生
发布2025-08-24 08:55:44
发布2025-08-24 08:55:44
15900
代码可运行
举报
运行总次数:0
代码可运行

🌟 开篇:初识 MediatR

在.NET 的修仙世界中,MediatR 就像是一本神奇的"传音入密"秘籍,它能让你的代码各司其职,却又心意相通。今天,就让我们一起来修炼这本秘籍,掌握.NET 中的中介者模式精髓! MediatR 是一个简单的中介者模式实现,它通过解耦消息发送者和接收者来简化应用程序中的进程内通信。简单来说,它就像是一个邮局,负责把你的"信件"(消息)准确无误地投递给正确的"收件人"(处理器)。

代码语言:javascript
代码运行次数:0
运行
复制

// 安装MediatR
dotnet add package MediatR

🏗️ 第一重境界:基础搭建

1. 配置 MediatR

首先,我们需要在 Startup.cs 或 Program.cs 中注册 MediatR 服务:

代码语言:javascript
代码运行次数:0
运行
复制

// .NET 6+ 的Program.cs
builder.Services.AddMediatR(cfg =>
    cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()));

2. 创建第一个消息和处理器

让我们从一个简单的"Hello World"开始:

代码语言:javascript
代码运行次数:0
运行
复制

// 定义消息
public class HelloWorldQuery:IRequest<string>
{
    publicstring Name {get;set;}
}

// 定义处理器
public class HelloWorldHandler

    :IRequestHandler<HelloWorldQuery,string>
{
    public Task<string>  Handle(

        HelloWorldQuery request,

        CancellationToken cancellationToken)
    {
        return Task.FromResult($"Hello, {request.Name}!");
    }
}

// 使用示例
var response =await mediator.Send(new HelloWorldQuery{ Name ="修仙者"});
Console.WriteLine(response);// 输出: Hello, 修仙者!

🧩 第二重境界:命令与查询

MediatR 支持两种主要模式:命令(Command)和查询(Query),对应 CQRS 模式。

1. 命令模式示例

代码语言:javascript
代码运行次数:0
运行
复制

// 创建用户命令
public class CreateUserCommand:IRequest<int>
{
    public string Username {get;set;}
    public string Email {get;set;}
}

public class CreateUserHandler

  :IRequestHandler<CreateUserCommand,int>
{
    privatereadonlyApplicationDbContext _context;

    public CreateUserHandler(ApplicationDbContext context)
    {
        _context = context;
    }

    public async Task<int>Handle(

        CreateUserCommand request,

        CancellationToken cancellationToken)
    {
        var user =new User
        {
            Username = request.Username,
            Email = request.Email
        };

        _context.Users.Add(user);
        await _context.SaveChangesAsync(cancellationToken);

        return user.Id;
    }
}

2. 查询模式示例

代码语言:javascript
代码运行次数:0
运行
复制

// 获取用户详情查询
public class GetUserByIdQuery:IRequest<UserDto>
{
    publicint UserId {get;set;}
}

public class GetUserByIdHandler

    :IRequestHandler<GetUserByIdQuery, UserDto>
{
    privatereadonlyApplicationDbContext _context;

    public GetUserByIdHandler(ApplicationDbContext context)
    {
        _context = context;
    }


public asyncTask<UserDto>Handle(GetUserByIdQuery request,CancellationToken cancellationToken)
{
var user =await _context.Users
.Where(u => u.Id == request.UserId)
.Select(u =>new UserDto
{
                Id = u.Id,
                Username = u.Username,
                Email = u.Email
})
.FirstOrDefaultAsync(cancellationToken);

return user ??throw new NotFoundException("User not found");
}
}

🔗 第三重境界:通知与事件

MediatR 还支持发布/订阅模式,通过 INotification 接口实现。

1. 定义通知事件

代码语言:javascript
代码运行次数:0
运行
复制

publicclassUserCreatedNotification:INotification
{
    public int UserId {get;set;}
    public string Username {get;set;}
    public DateTime CreatedAt {get;set;}
}

2. 创建多个处理器

代码语言:javascript
代码运行次数:0
运行
复制

// 发送欢迎邮件处理器
public class SendWelcomeEmailHandler:INotificationHandler<UserCreatedNotification>
{
    public async Task Handle(UserCreatedNotification notification,CancellationToken cancellationToken)
{
    // 模拟发送邮件
    Console.WriteLine($"发送欢迎邮件给 {notification.Username}");
    await Task.Delay(1000);
}
}

// 记录用户创建日志处理器
public class LogUserCreatedHandler:INotificationHandler<UserCreatedNotification>
{
private readonly ILogger<LogUserCreatedHandler> _logger;

public LogUserCreatedHandler(ILogger<LogUserCreatedHandler> logger)
{
        _logger = logger;
}

public Task Handle(UserCreatedNotification notification,CancellationToken cancellationToken)
{
        _logger.LogInformation("新用户创建: {UserId}, 用户名: {Username}",
            notification.UserId, notification.Username);
return Task.CompletedTask;
}
}

3. 发布通知

代码语言:javascript
代码运行次数:0
运行
复制

await mediator.Publish(new UserCreatedNotification
{
    UserId = newUserId,
    Username = command.Username,
    CreatedAt = DateTime.UtcNow
});

🛡️ 第四重境界:管道行为

MediatR 的管道行为(Pipeline Behaviors)类似于 ASP.NET Core 的中间件,可以在处理请求前后执行逻辑

1. 创建日志行为

代码语言:javascript
代码运行次数:0
运行
复制

public class LoggingBehavior<TRequest, TResponse>:IPipelineBehavior<TRequest, TResponse>
where TRequest:IRequest<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("处理请求 {RequestName} {@Request}",
typeof(TRequest).Name, request);

try
{
var response = await next();
            _logger.LogInformation("请求 {RequestName} 处理成功",typeof(TRequest).Name);
return response;
}
catch(Exception ex)
{
            _logger.LogError(ex,"请求 {RequestName} 处理出错",typeof(TRequest).Name);
throw;
}
}
}

2. 创建验证行为

代码语言:javascript
代码运行次数:0
运行
复制

public class ValidationBehavior<TRequest, TResponse>:IPipelineBehavior<TRequest, TResponse>
where TRequest:IRequest<TResponse>
{
private readonly IEnumerable<IValidator<TRequest>> _validators;

public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
{
        _validators = validators;
}

public async Task<TResponse>Handle(TRequest request,RequestHandlerDelegate<TResponse> next,CancellationToken cancellationToken)
{
if(_validators.Any())
{
var context =new ValidationContext<TRequest>(request);

var validationResults =await Task.WhenAll(
                _validators.Select(v => v.ValidateAsync(context, cancellationToken)));

var failures = validationResults
.SelectMany(r => r.Errors)
.Where(f => f !=null)
.ToList();

if(failures.Count !=0)
throw new ValidationException(failures);
}

return await next();
}
}

3. 注册行为

代码语言:javascript
代码运行次数:0
运行
复制

builder.Services.AddTransient(typeof(IPipelineBehavior<,>),typeof(LoggingBehavior<,>));
builder.Services.AddTransient(typeof(IPipelineBehavior<,>),typeof(ValidationBehavior<,>));

🎯 第五重境界:高级技巧

1. 使用 FluentValidation 进行验证

代码语言:javascript
代码运行次数:0
运行
复制

public class CreateUserCommandValidator:AbstractValidator<CreateUserCommand>
{
public CreateUserCommandValidator()
{
    RuleFor(x => x.Username)
    .NotEmpty().WithMessage("用户名不能为空")
    .MinimumLength(3).WithMessage("用户名至少3个字符")
    .MaximumLength(20).WithMessage("用户名最多20个字符");

    RuleFor(x => x.Email)
    .NotEmpty().WithMessage("邮箱不能为空")
    .EmailAddress().WithMessage("邮箱格式不正确");
}
}

// 注册验证器
builder.Services.AddValidatorsFromAssemblyContaining<CreateUserCommandValidator>();

2. 使用特性标记处理器

代码语言:javascript
代码运行次数:0
运行
复制

// 自定义特性
[AttributeUsage(AttributeTargets.Class)]
public class TransactionalAttribute:Attribute
{
}

// 创建事务行为
public class TransactionalBehavior<TRequest, TResponse>:IPipelineBehavior<TRequest, TResponse>
where TRequest:IRequest<TResponse>
{
private readonly ApplicationDbContext _context;

public TransactionalBehavior(ApplicationDbContext context)
{
        _context = context;
}

public async Task<TResponse>Handle(TRequest request,RequestHandlerDelegate<TResponse> next,CancellationToken cancellationToken)
{
// 检查是否标记了Transactional特性
if(request.GetType().GetCustomAttribute<TransactionalAttribute>()==null)
return await next();

await using var transaction =await _context.Database.BeginTransactionAsync(cancellationToken);

try
{
var response =await next();
await transaction.CommitAsync(cancellationToken);
return response;
}
catch
{
await transaction.RollbackAsync(cancellationToken);
throw;
}
}
}

3. 使用 MediatR 与 ASP.NET Core 集成

在控制器中使用 MediatR:

代码语言:javascript
代码运行次数:0
运行
复制

[ApiController]
[Route("api/users")]
public class UsersController:ControllerBase
{
privatereadonlyIMediator _mediator;

publicUsersController(IMediator mediator)
{
        _mediator = mediator;
}

[HttpPost]
publicasyncTask<IActionResult>CreateUser([FromBody]CreateUserCommand command)
{
var userId =await _mediator.Send(command);
returnCreatedAtAction(nameof(GetUser),new{ id = userId },null);
}

[HttpGet("{id}")]
publicasyncTask<ActionResult<UserDto>>GetUser(int id)
{
var query =newGetUserByIdQuery{ UserId = id };
var user =await _mediator.Send(query);
returnOk(user);
}
}

🌈 结语:MediatR 的修仙之道

1.通过今天的修炼,我们已经掌握了 MediatR 的五大境界:

  • ✅ 基础搭建 - 初识 MediatR
  • ✅ 命令与查询 - CQRS 模式实践
  • ✅ 通知与事件 - 发布/订阅模式
  • ✅ 管道行为 - 中间件式处理
  • ✅ 高级技巧 - 验证、事务等

2.MediatR 就像一把瑞士军刀,在.NET 应用程序中提供了灵活的消息传递机制。它能够:

  • ✅ 解耦组件之间的直接依赖
  • ✅ 简化控制器逻辑
  • ✅ 实现清晰的架构分层
  • ✅ 方便地添加横切关注点

记住,修仙之路漫长,MediatR 只是其中一本秘籍。希望这篇日记能助你在.NET 的修仙之路上更进一步!


📚 延伸阅读推荐:

💡 小测验:

  • 1.MediatR 主要实现了哪种设计模式?
  • 2.命令和查询在 MediatR 中有什么区别?
  • 3.如何为所有请求添加统一的日志记录?

欢迎在评论区分享你的答案和修炼心得!我们下期再见~


点击关注,修炼不迷路👇

▌转载请注明出处,渡人渡己

🌟 感谢道友结缘! 若本文助您突破修为瓶颈,不妨[打赏灵丹]或[转发功德],让更多.NET道友共参CLR天道玄机。修真之路漫漫,我们以代码为符,共绘仙途!

随缘赞赏即可

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-06-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 .NET修仙日记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 🌟 开篇:初识 MediatR
  • 🏗️ 第一重境界:基础搭建
    • 1. 配置 MediatR
    • 2. 创建第一个消息和处理器
  • 🧩 第二重境界:命令与查询
    • 1. 命令模式示例
    • 2. 查询模式示例
  • 🔗 第三重境界:通知与事件
    • 1. 定义通知事件
    • 2. 创建多个处理器
    • 3. 发布通知
  • 🛡️ 第四重境界:管道行为
    • 1. 创建日志行为
    • 2. 创建验证行为
    • 3. 注册行为
  • 🎯 第五重境界:高级技巧
    • 1. 使用 FluentValidation 进行验证
    • 2. 使用特性标记处理器
    • 3. 使用 MediatR 与 ASP.NET Core 集成
  • 🌈 结语:MediatR 的修仙之道
    • 1.通过今天的修炼,我们已经掌握了 MediatR 的五大境界:
    • 2.MediatR 就像一把瑞士军刀,在.NET 应用程序中提供了灵活的消息传递机制。它能够:
  • 📚 延伸阅读推荐:
  • 💡 小测验:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档