C# N服务总线,当有多个接口时按接口订阅

C# N服务总线,当有多个接口时按接口订阅,c#,nservicebus,C#,Nservicebus,使用NServiceBus,您可以通过接口进行订阅,例如: public class MyEvent: ISomeInterface {} public class Handler: IHandleMessages<ISomeInterface>{...} 公共类MyEvent:ISomeInterface{} 公共类处理程序:IHandleMessages{…} 这一切似乎都很好地工作,但是当您有多个接口时,例如: public class MyEvent: ISomeInt

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

public class MyEvent: ISomeInterface {}

public class Handler: IHandleMessages<ISomeInterface>{...}
公共类MyEvent:ISomeInterface{}
公共类处理程序:IHandleMessages{…}
这一切似乎都很好地工作,但是当您有多个接口时,例如:

public class MyEvent: ISomeInterface, ISomeOtherInterface {}

public class Handler: IHandleMessages<ISomeInterface>{/*Works fine*/}

public class Handler: IHandleMessages<ISomeOtherInterface>{/*Doesnt work*/}
公共类MyEvent:ISomeInterface,ISomeOtherInterface{}
公共类处理程序:IHandleMessages{/*工作正常*/}
公共类处理程序:IHandleMessages{/*不起作用*/}
使用发布/订阅时,无论哪种情况,都会正确订阅消息,但当消息实际发布时,接收服务会出现以下错误:

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

只有当您正在处理的接口是sent message类上的第一个接口时,它才会工作。如果我围绕第二个处理程序交换实际事件实现上的接口顺序,效果会很好,但第一个错误带有类似的消息(即接口顺序是导致问题的原因)

在构建消息时,无论接口的顺序如何,是否有办法通过接口处理消息?

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

编辑:

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

Configure.Features.Disable().Disable();
用()配置
.DefineEndpointName(“nsbinterfaces.subscriber”)
.DefiningEventsAs(t=>t.Namespace!=null&&t.Namespace.Contains(“.Events”))
//.NinjectBuilder(内核)
.DefaultBuilder()
.UseTransport()
.PurgeOnStartup(错误)
.MsmqSubscriptionStorage(“nsbinterfaces.subscriber”)
.UnicastBus()
.LoadMessageHandlers()
.ImpersonateSender(错误)
.CreateBus()
.开始(
()=>Configure.Instance.ForInstallationOn().Install());

看了这张照片后,我想我知道发生了什么

您的发布者知道自己的事件(MyEvent)及其实现的两个接口。这两个接口位于共享的程序集中

您的订阅者对MyEvent一无所知,因此不知道它实现了这两个接口。它是一个ISomeInterface或ISomeOtherInterface,因此它将其反序列化为这些类型之一

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


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


HTH

我在NSB论坛上问了这个问题,它已经转化为一个问题,看起来应该在软件的v5中解决。()

在修复之前,我认为有两种选择:

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

您使用的是哪个容器?看来很有可能与容器自动注册有关。@PhilSandler我正在使用NServicebus.Ninject适配器,我将在周一尝试将其替换为其他适配器,看看是否可以解决问题。它应该在这个用例中工作,不是吗?我没有错过一些好的东西,这是不允许的?你能分享代码来重现吗?@SeanFarmar请看我的编辑+示例复制solution@PhilSandler我也尝试使用默认生成器,但似乎没有任何帮助。还有其他想法吗?我认为这可能是对的,但它不应该反序列化到它有处理程序的所有类型吗?我不确定--我总是倾向于处理具体类型,所以我从来没有想到过这一点。有趣的是,如果您添加对发布服务器的引用,并为接口和具体类型添加处理程序,它们都会被命中。对于特定的支持论坛(google groups),这可能是一个很好的问题。谢谢,我会把它贴在那里,看看他们怎么说。卢克,我为此提出了一个问题。有关更多详细信息,请参阅:是的,这是可行的,但在我的实际应用程序中,我真的需要只发布单个接口,而不是它们的集合,因此不幸的是,这并不能解决我的问题。如果MyEvent位于NsbInterfaces.Events中,订阅者可以耦合到接口,而不是MyEvent。
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());
    <?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>