.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

