我正在尝试了解 MediatR 的工作原理。以前从未使用过这个库。下面的代码不是实际的生产代码。仅用于理解目的。
假设我有两个 RequestHandler。每个处理程序都将
ProductModel
作为请求,但返回不同类型的响应。
public class GetOrdersHandler : IRequestHandler<ProductModel, IEnumerable<Order>>
{
private readonly FakeDataStore _fakeDataStore;
public GetOrdersHandler(FakeDataStore fakeDataStore)
{
_fakeDataStore = fakeDataStore;
}
public async Task<IEnumerable<Order>> Handle(ProductModel request,CancellationToken cancellationToken
{
return await _fakeDataStore.GetAllOrdersForProduct(request);
}
}
public class SaveProductHandler : IRequestHandler<ProductModel, Product>
{
private readonly FakeDataStore _fakeDataStore;
public SaveProductHandler(FakeDataStore fakeDataStore)
{
_fakeDataStore = fakeDataStore;
}
public async Task<Product> Handle(ProductModel request,CancellationToken cancellationToken)
{
return await _fakeDataStore.SaveProduct(request);
}
}
然后在同一个控制器中我有两个操作方法
public class ProductsController : ControllerBase
{
private readonly IMediator _mediator;
public ProductsController(IMediator mediator) => _mediator = mediator;
[HttpPost]
public async Task<ActionResult> GetAllOrders(ProductModel model)
{
var product = await _mediator.Send(model);
return Ok(product);
}
[HttpPost]
public async Task<ActionResult> SaveProduct(ProductModel model)
{
var product = await _mediator.Send(model);
return Ok(product);
}
}
根据 MediatR 代码,这可能不起作用。看起来
Send
方法根据请求类型创建处理程序的实例。它保存 RequestType 和相应处理程序的字典。
如果我的假设是正确的,那么这是否意味着我必须为将使用
Send
方法的每个操作方法创建唯一的请求模型?
这是否意味着我必须为将使用 Send 方法的每个操作方法创建唯一的请求模型?
是的。
我们通常为每个请求创建一个类,并为每个响应创建一个类。
例如:
public class GetOrdersRequest : IRequest<GetOrdersResponse>
{
public Guid ProductId { get; set; }
}
public class GetOrdersResponse
{
public IEnumerable<Order> Orders { get; set; }
}
然后处理程序接收请求并返回响应。
public class GetOrdersHandler : IRequestHandler<GetOrdersRequest, GetOrdersResponse>
{
private readonly IOrdersRepository _ordersRepository;
public GetOrdersHandler(IOrdersRepository ordersRepository)
{
_ordersRepository = ordersRepository;
}
public async Task<GetOrdersResponse> Handle(GetOrdersRequest request, CancellationToken cancellationToken)
{
return new GetOrdersResponse
{
Orders = await _ordersRepository.GetOrdersThatContainProduct(request.ProductId)
}
}
}
这可以通过使用抽象类或接口轻松实现。
考虑以下内容:
public class CreateUserCommand()
: IRequestHandler<CreateUserRequest, ICreateUserResponse>
{
public async Task<ICreateUserResponse> Handle(CreateUserRequest request, CancellationToken cancellationToken)
{
var number = Random.Shared.Next(0, 100);
if (number % 2 == 0)
{
return await Task.FromResult(new UserCreatedResponse { });
}
else
{
return await Task.FromResult(new UserCreatedWithTwoFactorAuthenticaion { });
}
}
}
您的请求和响应模型可以是:
// Request command
public class CreateUserRequest : IRequest<ICreateUserResponse>
{
public required string Username { get; set; }
}
// Response command
public interface ICreateUserResponse
{
long UserId { get; }
}
响应实施可以是:
public class UserCreatedResponse : ICreateUserResponse
{
public long UserId { get; set; }
}
public class UserCreatedWithTwoFactorAuthenticaion : ICreateUserResponse, ITwoFactorAuth
{
public long UserId { get; set; }
public bool VerificationCodeSentOnEmail { get; set; }
}