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

.NET6 WebAPI中MediatR服务注册VS运行报错求助

问题

在基于.NET 6的WebAPI应用中,我通过反射为MediatR注册相关服务。通过Docker或命令提示符运行应用时程序能正常启动,但在Visual Studio中无论是否开启调试,都会触发如下异常:

InvalidOperationException: 激活'SagaInitiationCommand`1[Verte.UnifiedCommerce.MessagingModel.WarehouseManagement.AsnCommands.AsnGenerationCommand]'时,无法解析类型'Verte.UnifiedCommerce.MessagingModel.WarehouseManagement.AsnCommands.AsnGenerationCommand'的服务。

我的服务注册代码如下:

var eventType = typeof(IApplicationEvent);

var assemblies = typeof(AsnGenerationSaga).Assembly.GetReferencedAssemblies()
    .Select(a => Assembly.Load(a))
    .ToArray();

var commands = assemblies.SelectMany(a => a.GetTypes())
    .Where(t => !t.Name.Contains("ClientNotificationCommand") && !t.IsInterface && !t.IsAbstract && t.GetInterfaces().Any(i => i.FullName == eventType.FullName) && (t.IsSubclassOf(typeof(Command)) || t.IsSubclassOf(typeof(ModificationCommand))))
    .ToArray();

var events = assemblies.SelectMany(a => a.GetTypes())
    .Where(t => !t.IsInterface && !t.IsAbstract && t.GetInterfaces().Any(i => i.FullName == eventType.FullName) && t.IsSubclassOf(typeof(SagaEvent)))
    .ToArray();

services.AddMediatR(typeof(ProductsReader).Assembly);

foreach (var type in commands)
{
    var sagaInitiationCommandType = typeof(SagaInitiationCommand<>).MakeGenericType(type);
    var irequestHandlerType = typeof(IRequestHandler<,>).MakeGenericType(sagaInitiationCommandType, typeof(Unit));
    var sagaEventInitiatorType = typeof(SagaEventInitiator<,>).MakeGenericType(sagaInitiationCommandType, type);

    if (sagaEventInitiatorType != null)
    {
        services.AddTransient(typeof(IRequest<Unit>), sagaInitiationCommandType);
        services.AddTransient(irequestHandlerType, sagaEventInitiatorType);
    }
}

foreach (var type in events)
{
    var sagaPublishCommandType = typeof(SagaPublishEvent<>).MakeGenericType(type);
    var irequestHandlerType = typeof(IRequestHandler<,>).MakeGenericType(sagaPublishCommandType, typeof(Unit));
    var sagaEventInitiatorType = typeof(SagaEventInitiator<,>).MakeGenericType(sagaPublishCommandType, type);

    if (sagaEventInitiatorType != null)
    {
        services.AddTransient(typeof(IRequest<Unit>), sagaPublishCommandType);
        services.AddTransient(irequestHandlerType, sagaEventInitiatorType);
    }
}
解决方案

1. 注册命令/事件本身到DI容器

异常核心原因是SagaInitiationCommand<T>的构造函数依赖T类型实例,但你只注册了泛型包装类,未将T(如AsnGenerationCommand)本身注册到DI容器。Docker/命令行运行正常是因为发布模式下程序集加载策略不同,隐式处理了依赖,而VS环境需要显式注册。

修改遍历代码,先注册类型本身:

foreach (var type in commands)
{
    // 先注册命令类型本身,确保DI能解析它
    services.AddTransient(type);

    var sagaInitiationCommandType = typeof(SagaInitiationCommand<>).MakeGenericType(type);
    var irequestHandlerType = typeof(IRequestHandler<,>).MakeGenericType(sagaInitiationCommandType, typeof(Unit));
    var sagaEventInitiatorType = typeof(SagaEventInitiator<,>).MakeGenericType(sagaInitiationCommandType, type);

    if (sagaEventInitiatorType != null)
    {
        services.AddTransient(typeof(IRequest<Unit>), sagaInitiationCommandType);
        services.AddTransient(irequestHandlerType, sagaEventInitiatorType);
    }
}

foreach (var type in events)
{
    // 先注册事件类型本身
    services.AddTransient(type);

    var sagaPublishCommandType = typeof(SagaPublishEvent<>).MakeGenericType(type);
    var irequestHandlerType = typeof(IRequestHandler<,>).MakeGenericType(sagaPublishCommandType, typeof(Unit));
    var sagaEventInitiatorType = typeof(SagaEventInitiator<,>).MakeGenericType(sagaPublishCommandType, type);

    if (sagaEventInitiatorType != null)
    {
        services.AddTransient(typeof(IRequest<Unit>), sagaPublishCommandType);
        services.AddTransient(irequestHandlerType, sagaEventInitiatorType);
    }
}

2. 修复程序集加载的差异问题

VS调试/运行时,GetReferencedAssemblies()可能无法加载所有项目引用的程序集,导致反射找不到部分命令/事件类型。可以直接指定包含相关类型的程序集,避免依赖自动加载:

// 替换原来的assemblies获取逻辑,直接指定明确的程序集
var assemblies = new[] 
{
    typeof(AsnGenerationSaga).Assembly,
    typeof(AsnGenerationCommand).Assembly, // 命令所在程序集
    typeof(SagaEvent).Assembly // 事件基类所在程序集
};

3. 确保MediatR注册覆盖所有必要程序集

检查AddMediatR的注册范围,确保包含命令、事件和处理程序所在的所有程序集:

services.AddMediatR(cfg =>
{
    cfg.RegisterServicesFromAssembly(typeof(ProductsReader).Assembly);
    cfg.RegisterServicesFromAssembly(typeof(AsnGenerationCommand).Assembly);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 16:21:01