在 C# 中使用 MediatR 实现 Mediator 模式
在这篇文章中,我们将探讨 C# 中介模式的实现。要掌握中介模式的概念及其用例,我建议阅读我之前的博客。随着时间的推移,将调解器合并到应用程序中可能会导致复杂性增加。对于较小的应用程序,采用多种设计模式可能会引入不必要的复杂性。然而,随着应用程序的扩展,积累业务逻辑并遵守 KISS(保持简单、愚蠢)和 DRY(不要重复自己)等原则可能涉及在服务或经理之间直接调用。虽然依赖项注入可以解决紧密耦合问题,
在这篇文章中,我们将探讨 C# 中介模式的实现。要掌握中介模式的概念及其用例,我建议阅读我之前的博客。
随着时间的推移,将调解器合并到应用程序中可能会导致复杂性增加。对于较小的应用程序,采用多种设计模式可能会引入不必要的复杂性。然而,随着应用程序的扩展,积累业务逻辑并遵守 KISS(保持简单、愚蠢)和 DRY(不要重复自己)等原则可能涉及在服务或经理之间直接调用。虽然依赖项注入可以解决紧密耦合问题,但它仍然可能导致类在各种依赖项下变得繁琐。
这就是调解人模式被证明是有益的。在业务逻辑的上下文中,每个组件都与中介进行通信,而中介则承担促进不同组件之间通信的责任。中介模式找到实用工具的另一种情况是在 .NET 控制器中。您可以简单地注入一个中介器,使其能够处理与其他管理器的通信,而不是将所有管理器注入控制器。
误解
很多时候,人们听到与 CQRS 一起使用的中介模式,并认为 CQRS 需要中介模式。事实并非如此,您也可以在没有中介模式的情况下实现 CQRS。在 CQRS 中使用中介模式可以减少命令/查询和处理程序之间的耦合。我们将在以后的博客中看到 CQRS 和事件溯源示例。
MediatR
MediatR 是 Mediator 模式的 .NET 实现,它为同步和异步请求/响应、命令、查询、通知和事件提供支持。它采用使用 C# 泛型方差的智能调度。MediatR 简化了命令查询责任分离 (CQRS) 模式的采用,提供了一种管理命令和查询处理程序的简单方法。作为中介,MediatR 有效地将命令和查询定向到其指定的处理程序。
MediatR 的主要特点
解耦:MediatR 有助于将请求发送者(命令或查询)与其接收者(处理者)分离,从而有助于提高代码的可维护性和模块化。
管道行为:它适应管道行为的合并,允许轻松添加跨领域关注点,如验证、日志记录和身份验证。
自动发现处理程序:MediatR 具有自动识别和注册处理程序的能力,减少了对显式配置的需求。
例
让我们通过在电子商务应用程序中构建一个示例客户 API,来探索 C# 中 MediatR 的功能。在此上下文中,我们将命令和查询称为请求,负责处理它们的相应类将称为处理程序。
步骤 1:创建项目并安装所需的包
为此,我们将创建 2 个项目,一个称为 MediatRAPI,它将服务器客户 API。另一个名为 MediatRHandlers 的类库,我们在其中配置请求和请求处理程序。还可以使用以下命令安装 MediatR nuget 包。
dotnet add package MediatR
步骤 2:创建请求
让我们创建两个请求,如下所示,用于创建客户并按客户 ID 检索客户
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public string Address { get; set; }
}
using MediatR;
using MediatRHandlers.Entities;
namespace MediatRHandlers.Requests
{
public class CreateCustomerRequest : IRequest<int>
{
public Customer Customer { get; set; }
}
}
using MediatR;
using MediatRHandlers.Entities;
namespace MediatRHandlers.Requests
{
public class GetCustomerRequest : IRequest<Customer>
{
public int CustomerId { get; set; }
}
}
步骤 3:创建处理程序
对于上述每个请求,请创建处理程序,如下所示。
using MediatR;
using MediatRHandlers.Repositories;
using MediatRHandlers.Requests;
namespace MediatRHandlers.RequestHandlers
{
public class CreateCustomerHandler : IRequestHandler<CreateCustomerRequest, int>
{
//Inject Validators
private readonly ICustomerRepository _customerRepository;
public CreateCustomerHandler(ICustomerRepository customerRepository)
{
_customerRepository = customerRepository;
}
public async Task<int> Handle(CreateCustomerRequest request,
CancellationToken cancellationToken)
{
// First validate the request
return await _customerRepository.CreateCustomer(request.Customer);
}
}
}
using MediatR;
using MediatRHandlers.Entities;
using MediatRHandlers.Repositories;
using MediatRHandlers.Requests;
namespace MediatRHandlers.RequestHandlers
{
public class GetCustomerHandler : IRequestHandler<GetCustomerRequest, Customer>
{
private readonly ICustomerRepository _customerRepository;
public GetCustomerHandler(ICustomerRepository customerRepository)
{
_customerRepository = customerRepository;
}
public async Task<Customer> Handle(GetCustomerRequest request, CancellationToken cancellationToken)
{
return await _customerRepository.GetCustomer(request.CustomerId);
}
}
}
步骤 4:创建控制器
创建一个客户控制器,如下所示,如果您注意到我们没有注入所有处理程序,而是只注入中介器。
using MediatR;
using MediatRHandlers.Entities;
using MediatRHandlers.Requests;
using Microsoft.AspNetCore.Mvc;
namespace MediatRAPI.Controllers
{
[ApiController]
[Route("[controller]")]
public class CustomerController : ControllerBase
{
private readonly IMediator _mediator;
public CustomerController(IMediator mediator)
{
_mediator = mediator;
}
[HttpGet("customerId")]
public async Task<Customer?> GetCustomerAsync(int customerId)
{
var customerDetails = await _mediator.Send(new GetCustomerRequest() { CustomerId = customerId});
return customerDetails;
}
[HttpPost]
public async Task<int> CreateCustomerAsync(Customer customer)
{
var customerId = await _mediator.Send(new CreateCustomerRequest() { Customer = customer});
return customerId;
}
}
}
第 5 步:连接注册
在程序或启动文件中注册 MediatR 注册,如下所示。
using Microsoft.Extensions.DependencyInjection;
namespace MediatRHandlers
{
public static class MediatRDependencyHandler
{
public static IServiceCollection RegisterRequestHandlers(
this IServiceCollection services)
{
return services
.AddMediatR(cf => cf.RegisterServicesFromAssembly(typeof(MediatRDependencyHandler).Assembly));
}
}
}
using MediatRHandlers;
using MediatRHandlers.Repositories;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddScoped<ICustomerRepository, CustomerRepository>();
builder.Services.RegisterRequestHandlers();
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
app.Run();
步骤 6:运行 API
点击运行API项目后,您将看到客户API大摇大摆,您可以在其中测试创建客户并获取客户,如下所示。
在将 Mediator 模式纳入您的项目之前,彻底评估其优缺点至关重要。尽管它可以作为协调系统中对象之间通信的可靠解决方案,但它可能不是每个方案的最佳选择。
如果你喜欢我的文章,请给我一个赞!谢谢
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)