如何使用 MediatR 为同一请求模型获取不同的响应类型?

问题描述 投票:0回答:2

我正在尝试了解 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
方法的每个操作方法创建唯一的请求模型?

asp.net-mvc asp.net-core asp.net-core-mvc mediatr
2个回答
0
投票

这是否意味着我必须为将使用 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)
        }
    }
}

0
投票

这可以通过使用抽象类或接口轻松实现。

考虑以下内容:

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; }
}
© www.soinside.com 2019 - 2024. All rights reserved.