我正在处理我尚未编写的代码,并且正在尝试理解为什么某个特定功能不能按照我的意图运行。特别是,我的解决方案中有三个项目:
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
,所以默认行为不足以使它们可用于发布/订阅吗?即不应该删除有问题的3行没有效果吗?
答案 0 :(得分:0)
如果您不使用不引人注目的配置,事件的层次结构应如下所示:
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
对于仅实施false
的具体事件,这将评估为IMessage
,因此永远不会为您的活动调用RegisterEventRoute
,而是将其视为{{1} },遵循不同的路由规则(每IMessage
只有一个路由)。
答案 1 :(得分:0)
简而言之,如果您没有使用不显眼的配置,则必须在事件类上安装IEvent接口才能使用IBus.Publish。