如何配置 NServiceBus 以扫描程序集以查找 IMessage?

How do I configure NServiceBus to scan an assembly for IMessage?

我正在使用我没有编写过的代码,并试图理解为什么某个特定的功能没有按我预期的方式工作。特别是,我的解决方案中包含三个项目:

API
Messages
    Events
Processors

Events 是 Messages 中的一个文件夹。 API 将通过 Messages/Events 中定义的消息使用 NServiceBus 与处理器通信。 Messages/Events 中的每个 类 都扩展了 IMessage

现在,在处理器和 API 共享的总线配置文件中,我发现了这些行:

var conventionsBuilder = config.Conventions();
conventionsBuilder.DefiningEventsAs(t => t.Namespace != null && t.Namespace.StartsWith("DE.STEP.Messages") && t.Namespace.EndsWith("Events"));
return config;

这是较早实现的,Messages/Events 中的 类 并没有在较早的时间扩展 IMessage,而是上面的代码定义了消息可以在何处以及什么可以被限定为.现在,由于我已经引入了 IMessage,我想我可以删除那 3 行代码。但是,当我这样做时,没有消息从 API 进入我的队列。尝试发布的代码是 Bus.Publish<>();

我应该如何配置它,以便我不需要硬编码字符串来引用消息所在的程序集?我希望我的代码扫描解决方案以查找任何扩展 IMessage 的内容,并将其视为可以发布和处理的内容。

编辑:根据 NServiceBus 文档

By default, NServiceBus scans all assemblies in the endpoint 
bin folder to find types implementing its interfaces so that 
it can configure them automatically.

并且 Messages.dll 出现在 API 和处理器的 bin 中。因此,由于 Messages.dll 包含我所有的 IMessages,默认行为是否足以使它们可用于发布/订阅? IE。不应该删除有问题的 3 行没有效果吗?

事件的层次结构,如果您没有使用不显眼的配置,应该如下所示:

ConcreteEvent : IEvent : IMessage

这样做的原因是,在查看源代码后,您的消息端点映射处理如下:

foreach (var mapping in messageEndpointMappings)
{
    mapping.Configure((messageType, address) =>
    {
        var conventions = context.Settings.Get<Conventions>();
        if (!(conventions.IsMessageType(messageType) || conventions.IsEventType(messageType) || conventions.IsCommandType(messageType)))
        {
            return;
        }

        if (conventions.IsEventType(messageType))
        {
            router.RegisterEventRoute(messageType, address);
            return;
        }

        router.RegisterMessageRoute(messageType, address);
    });
}

Conventions.IsEventType是一个查找实现如下:

EventsConventionCache.ApplyConvention(t, type => IsEventTypeAction(type));

我不会给你完整的调用堆栈,但基本上,你会在这里结束:

t => typeof(IEvent).IsAssignableFrom(t) && typeof(IEvent) != t

对于仅实现 IMessage 的具体事件,这将评估为 false,因此永远不会为您的事件调用 RegisterEventRoute,而是将其视为 [=16] =],它遵循不同的路由规则(每个 IMessage 只有一条路由)。

简而言之,如果您没有使用不显眼的配置,您的事件 class 必须有 IEvent 接口才能使用 IBus.Publish。