You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core 7 Minimal API+MediatR的DI错误排查与解决

.NET Core 7 Minimal API依赖注入错误排查与解决

运行基于.NET Core 7的Minimal API时,遇到依赖注入相关错误,以下是相关代码与错误信息:

端点代码

public static void DefineEndpoints(IEndpointRouteBuilder app)
{
    app.MapPost(BaseRoute, NewStoredFileTypeAsync)
        .WithTags(Tag);
}

private static async Task<Guid> NewStoredFileTypeAsync(NewStoredFileTypeDto request, IMediator mediator)
{
    var messageId = new MessageId(Guid.NewGuid());
    var command = new NewStoredFileTypeCommand()
    {
        Id = messageId,
        CorrelationId = new CorrelationId(Guid.Parse(messageId.ToString())),
        CausationId = new CausationId(Guid.Parse(messageId.ToString())),
        CommandDto = request,
    };

    var response = await mediator.Send(command);
    return response;
}

命令代码

public class NewStoredFileTypeCommand : BaseCommand, IRequest<Guid>
{
    public NewStoredFileTypeDto CommandDto { get; set; } = default!;
}

命令处理器代码

public class NewStoredFileTypeCommandHandler : IRequestHandler<NewStoredFileTypeCommand, Guid>  
{  
    private readonly IMapper _mapper;  
    private readonly IEventSourcingHandler<StoredFileType, StoredFileTypeId> _eventSourcingHandler;

    public NewStoredFileTypeCommandHandler(IMapper mapper,                                                     
        IEventSourcingHandler<StoredFileType, StoredFileTypeId> eventSourcingHandler)                          
    {                                                                                                          
        _mapper = mapper;                                                                                      
        _eventSourcingHandler = eventSourcingHandler;                                                          
    }                                                                                                          

    public async Task<Guid> Handle(NewStoredFileTypeCommand request, CancellationToken cancellationToken)       
    {                                                                                                          
        var response = new BaseCommandResponse<StoredFileTypeId>();                                            

        var aggregate = new StoredFileType(                                                                    
            new StoredFileTypeId(Guid.NewGuid()),                                                              
            request.CorrelationId,                                                                             
            new CausationId(Guid.Parse(request.Id.ToString())),                                                
            request.CommandDto.Name, request.CommandDto.IsImageFileType,                                       
            _mapper.Map<BootstrapIconCode>(request.CommandDto.BootstrapIconCode)                               
            );                                                                                                 

        await _eventSourcingHandler.SaveAsync(aggregate);                                                      
        return Guid.Parse(aggregate.Id.ToString());                                                            
    }                                                                                                          
}

IMongoDbRepository接口

public interface IMongoDbRepository<TEntityId, TEntity> : IRepository<TEntityId, TEntity>
{
    
}

MongoDbRepository实现

public class MongoDbRepository<TObjectId, TEntity> : IMongoDbRepository<string, TEntity>
    where TEntity : IMongoDocument
{
    private readonly IMongoDbSettings _dbSettings;
    private readonly IMongoCollection<TEntity> _collection;
    
    public MongoDbRepository(IMongoDbSettings dbSettings)
    {
        _dbSettings = dbSettings;

        var connectionFactory = new MongoDbConnectionFactory<TEntity>(_dbSettings);
        _collection = connectionFactory.GetCollection();
    }

    public async Task<bool> InsertAsync(TEntity entity)
    {
        await _collection.InsertOneAsync(entity);
        return true;
    }

    public async Task<bool> UpdateAsync(TEntity entity)
    {
        throw new NotImplementedException();
    }

    public async Task<bool> DeleteAsync(TEntity entity)
    {
        throw new NotImplementedException();
    }

    public async Task<IList<TEntity>> SearchForAsync(Expression<Func<TEntity, bool>> predicate)
    {
        return await _collection.Find(predicate).ToListAsync();
    }

    public async Task<IList<TEntity>> GetAllAsync()
    {
        return await _collection.Find(_ => true).ToListAsync();
    }

    public async Task<TEntity> GetByIdAsync(string id)
    {
        throw new NotImplementedException();
    }
}

MongoDB仓储注册代码

public static IServiceCollection AddMongoDb(this IServiceCollection services, IConfiguration configuration)
{
    //从appsettings.json获取连接字符串并填充MongoDbSettings类
    services.Configure<MongoDbSettings>(configuration.GetSection(nameof(MongoDbSettings)));
    services.AddSingleton<IMongoDbSettings>(serviceProvider =>
        serviceProvider.GetRequiredService<IOptions<MongoDbSettings>>().Value);
    
    //添加泛型仓储
    services.AddScoped(typeof(IMongoDbRepository<,>), typeof(MongoDbRepository<,>));

    return services;
}

错误信息

未处理的异常。System.AggregateException: 无法构造某些服务(验证服务描述符时出错 'ServiceType: MediatR.IRequestHandler2[mNet.FileServer.Commands.Ui.MinimalApi.Features.StoredFileTypes.NewStoredFileType.NewStoredFileTypeCommand,System.Guid] Lifetime: Transient ImplementationType: mNet.FileServer.Commands.Ui.MinimalApi.Features.StoredFileTypes.NewStoredFileType.NewStoredFileTypeCommandHandler': 实现类型'mNet.Common.Infrastructure.Persistence.MongoDbImplementation.MongoDbRepository2[mNet.FileServer.Commands.Domain.Aggregates.StoredFileTypes.ValueObjects.StoredFileTypeId,mNet.Common.Infrastructure.Persistence.MongoDbImplementation.MongoDbEventDocument`1[mNet.FileServer.Commands.Domain.Aggregates.StoredFileTypes.ValueObjects.StoredFileTypeId]]'无法转换为服务类型'mNet.Common.Infrastructure.Persistence.Contracts.Repositories.IMongoDbRepository`2[mNet.FileServer.Commands.Domain.Aggregates.StoredFileTypes.ValueObjects.StoredFileTypeId,mNet.Common.Infrastructure.Persistence.MongoDbImplementation.MongoDbEventDocument`1[mNet.FileServer.Commands.Domain.Aggregates.StoredFileTypes.ValueObjects.StoredFileTypeId]]')


错误原因

核心问题在于MongoDbRepository的泛型实现与接口不匹配:

  • 接口定义为IMongoDbRepository<TEntityId, TEntity>,允许第一个泛型参数为任意实体ID类型(如你的StoredFileTypeId)
  • 但你的MongoDbRepository<TObjectId, TEntity>硬编码实现了IMongoDbRepository<string, TEntity>,固定第一个参数为string
  • 当DI容器尝试解析IMongoDbRepository<StoredFileTypeId, MongoDbEventDocument<StoredFileTypeId>>时,找不到匹配的实现,因为你的仓储只实现了string作为ID类型的版本

解决方案

修改MongoDbRepository的实现,使其泛型参数与接口对齐,并处理自定义ID类型与MongoDB字符串ID的转换:

  1. 调整仓储类的继承关系:
public class MongoDbRepository<TEntityId, TEntity> : IMongoDbRepository<TEntityId, TEntity>
    where TEntity : IMongoDocument
{
    private readonly IMongoDbSettings _dbSettings;
    private readonly IMongoCollection<TEntity> _collection;
    
    public MongoDbRepository(IMongoDbSettings dbSettings)
    {
        _dbSettings = dbSettings;
        var connectionFactory = new MongoDbConnectionFactory<TEntity>(_dbSettings);
        _collection = connectionFactory.GetCollection();
    }

    // ... 其他方法保持不变 ...

    public async Task<TEntity> GetByIdAsync(TEntityId id)
    {
        // 假设你的自定义ID类型(如StoredFileTypeId)可以转换为string
        var stringId = id.ToString();
        return await _collection.Find(x => x.Id == stringId).FirstOrDefaultAsync();
    }
}
  1. 确保你的StoredFileTypeId值对象正确实现ToString()方法,返回对应的Guid字符串(因为MongoDB文档ID通常是字符串格式的Guid)

  2. 如果你的IMongoDocument接口定义的Id不是string类型,需要额外处理ID的映射逻辑


内容的提问来源于stack exchange,提问作者dmeadley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 12:15:33