如何在MediatR模式中传递对象数组作为请求参数?
解决MediatR批量请求的CS0311错误
错误原因
你遇到的CS0311错误,本质是**AddFieldCommand[]数组没有实现MediatR的IRequest<TResponse>接口**,不符合IRequestHandler<TRequest, TResponse>对泛型参数TRequest的要求——它必须是实现了IRequest的具体类型,而数组类型不满足这个约束。
解决方案
MediatR的设计模式是单个请求对应单个处理器,要处理批量添加场景,需要创建一个包含请求集合的"聚合请求类",而非直接使用数组作为参数。具体步骤如下:
1. 创建聚合请求类
新建一个包含AddFieldCommand集合的请求类,并让它实现IRequest<TResponse>接口(这里返回批量添加的ID列表,可根据业务调整返回类型):
public class AddFieldsCommand : IRequest<ServiceResponse<List<int>>> { // 存储批量添加的字段命令集合 public List<AddFieldCommand> FieldCommands { get; set; } = new List<AddFieldCommand>(); }
2. 编写对应的批量处理器
创建处理AddFieldsCommand的处理器,在Handle方法中实现批量添加逻辑:
public class AddFieldsCommandHandler : IRequestHandler<AddFieldsCommand, ServiceResponse<List<int>>> { private readonly IFieldsService _fieldService; public AddFieldsCommandHandler(IFieldsService fieldService) { _fieldService = fieldService; } public async Task<ServiceResponse<List<int>>> Handle(AddFieldsCommand request, CancellationToken cancellationToken) { var addedIds = new List<int>(); // 遍历集合处理单个添加逻辑 foreach (var fieldCmd in request.FieldCommands) { var response = await _fieldService.AddField(fieldCmd, cancellationToken); if (response.Success) { addedIds.Add(response.Data); } // 可根据业务需求处理失败场景:比如中断流程返回错误,或记录错误后继续执行 } return new ServiceResponse<List<int>> { Success = true, Data = addedIds }; } }
3. 修改控制器方法
将控制器参数替换为新的聚合请求类,然后通过MediatR发送请求:
public async Task<ActionResult<ServiceResponse<List<int>>>> AddField(AddFieldsCommand objFieldsCommand) { return await _mediator.Send(objFieldsCommand); }
可选优化:事务处理
如果需要保证批量操作的原子性(要么全部成功,要么全部失败),可以在Handler中引入事务:
// 假设使用EF Core,注入DbContext private readonly AppDbContext _dbContext; public AddFieldsCommandHandler(IFieldsService fieldService, AppDbContext dbContext) { _fieldService = fieldService; _dbContext = dbContext; } public async Task<ServiceResponse<List<int>>> Handle(AddFieldsCommand request, CancellationToken cancellationToken) { using var transaction = await _dbContext.Database.BeginTransactionAsync(cancellationToken); try { var addedIds = new List<int>(); foreach (var fieldCmd in request.FieldCommands) { var response = await _fieldService.AddField(fieldCmd, cancellationToken); if (!response.Success) { throw new Exception(response.Message); } addedIds.Add(response.Data); } await _dbContext.SaveChangesAsync(cancellationToken); await transaction.CommitAsync(cancellationToken); return new ServiceResponse<List<int>> { Success = true, Data = addedIds }; } catch (Exception ex) { await transaction.RollbackAsync(cancellationToken); return new ServiceResponse<List<int>> { Success = false, Message = ex.Message }; } }
内容的提问来源于stack exchange,提问作者Rahul Parab
相关产品推荐
相关产品推荐

