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

NServiceBus 7.5迁移至8:WindsorContainer依赖适配问题求助

NServiceBus 8 迁移Windsor容器依赖加载问题

问题背景

我们之前基于NServiceBus 7.5 + Windsor容器开发,通过FromAssemblyContaining批量加载项目依赖,用以下代码关联NServiceBus和现有容器:

endpointConfiguration.UseContainer<WindsorBuilder>(c => c.ExistingContainer(container));

服务运行正常,但升级到NServiceBus 8后,UseContainer方法被移除,官方要求通过AddSingleton、AddScoped或AddTransient逐个注册依赖。但我们没法枚举FromAssemblyContaining加载的所有服务,不知道如何批量迁移现有容器中的依赖。

尝试过的方案及错误

我们参考官方迁移文档实现了以下代码:

var endpointConfiguration = new EndpointConfiguration("EndpointName");
_endpointCustomization.Customize(endpointConfiguration); // 配置端点相关内容
var serviceCollection = new ServiceCollection();
var container = _endpointCustomization.Container(); // 获取已加载好的Windsor容器
var serviceProvider = WindsorRegistrationHelper.CreateServiceProvider(container, serviceCollection);
var startableEndpoint = EndpointWithExternallyManagedContainer.Create(endpointConfiguration, serviceCollection);
var _endpointInstance = await startableEndpoint.Start(serviceProvider);
await _endpointCustomization.Start(_endpointInstance);

但调用第一个await时抛出异常:

Castle.MicroKernel.ComponentNotFoundException: 未找到支持服务NServiceBus.Unicast.Messages.MessageMetadataRegistry的组件

解决方案

问题根源是NServiceBus 8所需的内部服务没有被注册到Windsor容器中。正确的做法是先让NServiceBus把自身依赖注册到ServiceCollection,再将Windsor容器中的现有服务批量导入到ServiceCollection,最后用整合后的服务集合创建ServiceProvider并启动端点。

正确代码示例

var endpointConfiguration = new EndpointConfiguration("EndpointName");
_endpointCustomization.Customize(endpointConfiguration);

// 1. 让NServiceBus将自身所需的内部服务注册到ServiceCollection
var serviceCollection = new ServiceCollection();
endpointConfiguration.ApplyCommonConfiguration(serviceCollection);

// 2. 获取已完成依赖加载的Windsor容器
var container = _endpointCustomization.Container();

// 3. 批量将Windsor容器中的服务导入到ServiceCollection
foreach (var component in container.Kernel.GetAssignableHandlers(typeof(object)))
{
    var serviceType = component.ComponentModel.Service;
    var implementationType = component.ComponentModel.Implementation;
    var lifestyle = component.ComponentModel.LifestyleType;

    // 根据Windsor生命周期映射到ServiceCollection的注册方式
    switch (lifestyle)
    {
        case LifestyleType.Singleton:
            serviceCollection.AddSingleton(serviceType, implementationType);
            break;
        case LifestyleType.Scoped:
            serviceCollection.AddScoped(serviceType, implementationType);
            break;
        case LifestyleType.Transient:
            serviceCollection.AddTransient(serviceType, implementationType);
            break;
        // 处理自定义生命周期,比如PerWebRequest等,可根据实际需求调整
        default:
            serviceCollection.AddTransient(serviceType, implementationType);
            break;
    }
}

// 4. 创建ServiceProvider并启动端点
var serviceProvider = serviceCollection.BuildServiceProvider();
var startableEndpoint = EndpointWithExternallyManagedContainer.Create(endpointConfiguration, serviceCollection);
var _endpointInstance = await startableEndpoint.Start(serviceProvider);
await _endpointCustomization.Start(_endpointInstance);

关键说明

  • ApplyCommonConfiguration是NServiceBus 8新增的方法,用于将端点运行所需的内部服务(比如MessageMetadataRegistry)注册到ServiceCollection,这是之前方案缺失的核心步骤
  • 通过遍历Windsor容器的GetAssignableHandlers,可以批量获取所有已注册的服务,无需逐个枚举,完美替代FromAssemblyContaining的批量加载逻辑
  • 注意保持Windsor和ServiceCollection的生命周期一致,避免因生命周期不匹配导致的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 07:17:44