Search code examples
castle-windsorrebusrebus-azureservicebus

Rebus, using Castle Windsor with Rebus


I'm trying to use Rebus with Azure Service Bus and Castle Windsor. When I use the version of my code without Castle Windsor, queues and topics are created correctly:

public static void Main(string[] args)
{
    using (var activator = new BuiltinHandlerActivator())
    {
        activator.Register(() => new SomeMessageHandler());
        activator.Register(() => new BusItemMessageHandler());
        Configure.With(activator)
            .Logging(l => l.ColoredConsole(minLevel: LogLevel.Warn))
            .Transport(t => t.UseAzureServiceBus(GetConnectionString(), "ReceiverInputQueue"))
            .Start();
        activator.Bus.Subscribe<SomeMessage>().Wait();
        activator.Bus.Subscribe<IBusItem>().Wait();
        Console.ReadLine();
        Console.WriteLine("Quitting...");
    }
}

..but when I try to use Castle Windsor, just the queues are created (no topics):

public static void Main(string[] args)
{
    using (var container = new WindsorContainer())
    {
        //container.Register(Classes.FromAssemblyContaining<BusItemMessageHandler>()
        //  .BasedOn<IHandleMessages>()
        //  .WithServiceAllInterfaces()
        //  .LifestyleTransient());
        container.AutoRegisterHandlersFromAssemblyOf<BusItemMessageHandler>();
        var adapter = new CastleWindsorContainerAdapter(container);
        Configure.With(adapter)
            .Logging(l => l.ColoredConsole(minLevel: LogLevel.Warn))
            .Transport(t => t.UseAzureServiceBus(GetConnectionString(), "ReceiverInputQueue"))
            .Start();
        Console.WriteLine("Press ENTER to quit");
        Console.ReadLine();
        Console.WriteLine("Quitting...");
    }
}

Here the message/handlers:

public class BusItemMessageHandler : IHandleMessages<IBusItem>
{
    public async Task Handle(IBusItem message)
    {
        var a = message;
    }
}
public class SomeMessageHandler : IHandleMessages<SomeMessage>
{
    public async Task Handle(SomeMessage message)
    {
        Console.WriteLine($"Got string: {message.Message}");
    }
}
public class SomeMessage : IBusItem
{
    public Guid BusItemId { get; set; } = Guid.NewGuid();
    public DateTime Timestamp { get; set; } = DateTime.UtcNow;
    public string Message { get; set; }
}

What is wrong? Any suggestions? Thanks!


Solution

  • With Rebus and Azure Service Bus, topics are created when

    a) a publisher first publishes to it, or b) a subscriber first subscribes to it

    When I compare your two code snippets, the two lines with

    activator.Bus.Subscribe<SomeMessage>().Wait();
    activator.Bus.Subscribe<IBusItem>().Wait();
    

    are missing from snippet #2.

    If you do this:

    var bus = container.Resolve<ISyncBus>(); //< NOTE: SYNC BUS!
    
    bus.Subscribe<SomeMessage>();
    

    I bet you'll get the expected topic! 🙂


    PS: Subscribing to IBusItem has no effect, unless you modify how Rebus maps .NET types to topics. When you publish an instance of SomeMessage, it will be published to a topic named after that type (e.g. something like SomeNamespace.SomeMessage__SomeAssembly).

    You can still have a handler implement IHandleMessages<IBusItem> though. The polymorphic dispatch mechanism kicks in after a message is received, so as long as you subscribe to all the necessary types, the dispatch mechanism will dispatch to all compatible handlers.