【问题标题】:How do I configure NServiceBus to scan an assembly for IMessage?如何配置 NServiceBus 以扫描程序集以查找 IMessage?
【发布时间】:2015-03-16 14:59:13
【问题描述】:

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

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 行没有效果吗?

【问题讨论】:

  • 您是否尝试过 1) 实施 IEvent 而不是 IMessage 和 2) 您的消息端点映射设置是否正确?
  • 消息端点映射确实是正确的,正如我所说的那 3 行专门指定在哪里查找消息,整个管道都有效。我可以试试IEvent 的东西,虽然我不明白为什么这对IMessage 有效,因为后者只是比前者更广泛的定义
  • 如果更改为 IEvent 不起作用,您能否分享单个事件的映射?查看事件与消息的路由规则,您似乎只能为每条消息设置一个路由,因为代码不知道它是命令还是事件。因此,在消息的情况下,它会清除消息的所有路由,并且只跟踪文件中该类型的最后一个。
  • 成功了!如果您想发布答案,我会批准它

标签: c# nservicebus messaging


【解决方案1】:

一个事件的层次结构,如果你不使用不显眼的配置,应该如下:

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,而是将其视为IMessage,它遵循不同的路由规则(仅每个IMessage 一条路线。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多