如何在NServiceBus中手动处理任何订阅的消息类型?

时间:2011-03-14 06:43:33

标签: message-queue nservicebus

我正在尝试在NServiceBus上构建一个层,以便其他开发人员使用它。

我正在尝试不使用配置文件并设法让发布者工作:

public class NServiceBusPublisher
{
    private IBus _Bus { get; set; }

    public void NServiceBusPublisher(string argInputQueue, string argErrorQueue)
    {
        Configure configure = NServiceBus.Configure.With().DefaultBuilder();
        var transport = configure.Configurer.ConfigureComponent<MsmqTransport>(ComponentCallModelEnum.Singleton);

        transport.ConfigureProperty(t => t.InputQueue, argInputQueue);
        transport.ConfigureProperty(t => t.ErrorQueue, argErrorQueue);
        transport.ConfigureProperty(t => t.NumberOfWorkerThreads, 1);
        transport.ConfigureProperty(t => t.MaxRetries, 5);

        _Bus =
            configure
            .XmlSerializer()
            .MsmqTransport()
                        .IsTransactional(true)
                        .PurgeOnStartup(false)
                    .MsmqSubscriptionStorage()  
            .UnicastBus()
                .ImpersonateSender(false)
            .CreateBus()
            .Start();

    }

    public void Publish(NServiceBus.IMessage argMessage)
    {
        _Bus.Publish(argMessage);
    }
}

我还希望拥有一个NServiceBus订阅服务器,并且只要消息继承自NServiceBus.IMessage,开发人员就可以订阅任意数量的消息类型:

    public class NServiceBusSubscriber      
{
    private IBus _Bus { get; set; }

    public void NServiceBusSubscriber(string argInputQueue, string argOutputQueue, string argErrorQueue, string messagesAssembly)
    {
        Configure configure = NServiceBus.Configure.With().DefaultBuilder();

        var transport = configure.Configurer.ConfigureComponent<MsmqTransport>(ComponentCallModelEnum.Singleton);
        transport.ConfigureProperty(t => t.InputQueue, argInputQueue);
        transport.ConfigureProperty(t => t.ErrorQueue, argErrorQueue);
        transport.ConfigureProperty(t => t.NumberOfWorkerThreads, 1);
        transport.ConfigureProperty(t => t.MaxRetries, 5);

        var ucb = configure.Configurer.ConfigureComponent<NServiceBus.Unicast.UnicastBus>(ComponentCallModelEnum.Singleton);
        ucb.ConfigureProperty(u => u.MessageOwners, new Dictionary<string,string>()
        {
            {messagesAssembly, argOutputQueue}
        });

        _Bus =
            configure
            .XmlSerializer()
            .MsmqTransport()
                        .IsTransactional(true)
                        .PurgeOnStartup(false)
                    .MsmqSubscriptionStorage()                      
            .UnicastBus()
                .ImpersonateSender(false)
            .DoNotAutoSubscribe()
            .CreateBus()
            .Start();

    }

    public void Subscribe<T>() where T : NServiceBus.IMessage
    {
        _Bus.Subscribe<T>();
    }
} 

问题是我找不到任何方法将事件处理程序附加到特定的消息类型。

你能帮我解决这个问题吗?

非常感谢。

4 个答案:

答案 0 :(得分:1)

问题被问到已经有一段时间了,所以我不确定问题是否已经解决,但是这是使用Bus.Subscribe进行的一种方式(尽管其他受访者已经说过这不是这样做的规定方式NServiceBus)

使用subscribe overload

订阅消息类型
    void Subscribe(Type messageType, Predicate<IMessage> condition);

然后您可以处理委托中的消息

    private bool Handle(NServiceBus.IMessage nsbMsg)
    {
       //you get the message instance that you can handle
       //return true
    }

因此,您的代码将是

    class MySubscriber
    {
      public IBus Bus {get; set;}

      public void Subscribe()
      {
        Bus.Subscribe(typeof(MyMessage), Handle);
      }    

      public void Handle(NServiceBus.IMessage nsbMsg)
      {
        var msg = nsbMsg as MyMessage;

        //your code
        return true;
      } 
    }

但请注意,通过这样做,您必须自己管理处理程序的生命周期,否则NServiceBus将使用您选择的IOC框架为您管理。

如果您只是实现了IHandleMessage接口,那么您还必须明确地传递对IBus的引用,这将自动注入。

这里的架构点是NSB是一个完整的'ESB',它不仅仅是一个消息传递层。在你的ESB上添加另一层是恕我直言,抽象太多了。

答案 1 :(得分:1)

我认为您缺少NServiceBus背后的概念。

基于您显示的代码,我给人的印象是,您设想了发布消息的服务以及处理这些消息的其他服务。以我的经验,大多数进程都做这两种事情:它们订阅事件或处理传入的命令,结果发布新事件并发送新命令。 在您的设置中,您需要为每种消息类型具有发布者和订阅者实例。

NServiceBus是针对我所描述的情况而构建的。您配置并启动1个总线实例,这将协调整个应用程序。

如果要使开发人员更轻松地使用NServiceBus,我将只专注于配置部分。在我们公司中,我创建了一个ServicebusConfigurator类,该类根据我们公司的标准配置NServiceBus,并将其提取到.NET Core通用主机的框架和简单扩展方法中。开发人员只需编写以下代码即可创建一个承载NServiceBus终结点的Windows服务:

Text("something",style:isBold?_boldTextStyle:_normalTextStyle);

答案 2 :(得分:0)

由于您没有自动订阅,您需要做的第一件事是通过Bus.Subscribe()订阅消息类型。其他人可以在IWantToRunAtStartUp扩展点执行此操作(在某个类中实现接口)。从那里,每个订户将实现IHandleMessages&lt; T&gt;。接口。实现此接口会将您连接到消息,其中“T”是消息类型。

当NSB启动时,它将扫描本地bin目录并找到所有接口实现并在内部代表您连接它们。当那个类型的消息到达时,它会从那里调度到正确的处理程序。

答案 3 :(得分:0)

NServiceBus自动处理邮件订阅。当你调用Configure.With().... Start(); NServiceBus将扫描以确定哪些程序集实现了IHandleMessages(SomeMessage),它将向发布者发送订阅请求。

当您添加“DoNotAutoSubscribe”时,您必须手动获取正在处理的所有邮件,并为每个邮件执行Bus.Subscribe()。

除此之外,NServiceBus将自动处理传入消息到适当处理程序的路由。在上面的用户代码中,您是否收到错误消息或消息是否从队列中消失?