NServiceBus,当有多个接口时按接口订阅

本文关键字:接口 NServiceBus | 更新日期: 2023-09-27 18:17:16

使用NServiceBus,您可以通过接口订阅,例如:

public class MyEvent: ISomeInterface {}
public class Handler: IHandleMessages<ISomeInterface>{...}

这一切似乎工作愉快,但是当你有多个接口,例如:

public class MyEvent: ISomeInterface, ISomeOtherInterface {}
public class Handler: IHandleMessages<ISomeInterface>{/*Works fine*/}
public class Handler: IHandleMessages<ISomeOtherInterface>{/*Doesnt work*/}

当使用pub/sub时,消息在两种情况下都被正确订阅,但是当消息实际发布时,接收服务错误:

找不到消息类型的处理程序:ISomeInterface

似乎只有当您正在处理的接口是发送消息类上的第一个接口时才有效。如果我在第二个处理程序周围的实际事件实现上交换接口的顺序,则工作良好,但第一个错误具有类似的消息(即接口顺序是导致问题的原因)

是否有某种方法可以通过接口处理消息,而不管在构造消息时接口的顺序是什么?

我已经尝试过使用NSB 3和NSB 4的处理程序产生相同的结果。

编辑:

根据要求,这里是我正在使用的订阅者配置的更详细的片段。我还把一个最小的repro pub/sub应用程序来演示我遇到的问题(在github这里)。

Configure.Features.Disable<NServiceBus.Features.TimeoutManager>().Disable<NServiceBus.Features.SecondLevelRetries>();
Configure.With()
    .DefineEndpointName("nsbinterfaces.subscriber")
    .DefiningEventsAs(t => t.Namespace != null && t.Namespace.Contains(".Events"))
    //.NinjectBuilder(kernel)
    .DefaultBuilder()
    .UseTransport<Msmq>()
        .PurgeOnStartup(false)
    .MsmqSubscriptionStorage("nsbinterfaces.subscriber")
    .UnicastBus()
        .LoadMessageHandlers()
        .ImpersonateSender(false)
    .CreateBus()
    .Start(
        () => Configure.Instance.ForInstallationOn<NServiceBus.Installation.Environments.Windows>().Install());

NServiceBus,当有多个接口时按接口订阅

看了报告后,我想我知道是怎么回事了。

你的Publisher知道它自己的事件(MyEvent)和它实现的两个接口。这两个接口位于共享的程序集中。

你的订阅者对MyEvent一无所知,所以它不知道它实现了两个接口。它要么是一个ISomeInterface,要么是一个ISomeOtherInterface,所以它将它反序列化为这些类型中的一个

由于接口的顺序似乎决定了接收到的消息的类型,我猜测NSB将把消息反序列化为它所看到的第一种类型(每个进程)。

    <?xml version="1.0"?>
    <Messages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"    
     xmlns="http://tempuri.net/NsbInterfaces.Publisher.Events" 
     xmlns:baseType="NsbInterfaces.Events.ISomeInterface" 
     xmlns:baseType1="NsbInterfaces.Events.ISomeOtherInterface">    
    <MyEvent></MyEvent>
    </Messages>

您需要将您的接口实现移动到共享程序集(NsbInterfaces.Events)

添加一个pull request到你的repo

HTH

我在NSB论坛上问过这个问题,它被转化为一个问题,看起来应该在软件的v5中解决。(https://github.com/Particular/NServiceBus/issues/2301)

在它被修复之前,我认为有两个选择:

  • 将其作为两个单独的消息发送
  • 将实现放入已发布的库中(感谢@seanfarmar)