Provides extensions to make to the "No code sharing" scenario easier to configure on Rebus. Also it aims to introduce no breaking changes and even be able to have both scenarios at the same time, with or without sharing a dll.
See this issue rebus-org/Rebus#852
How is it better than the "SharedNothing" sample provided?
The sample providade still depends on the fully quallified type name (including the assembly) to be able to deserialize the messages, as you can see here:
On the other hand, with this repo's implementation, the applications only have to agree on a topic name
using Microsoft.Extensions.DependencyInjection;
using Rebus.ServiceProvider;
using Rebus.Extensions.SharedNothing;
using Rebus.Config;
namespace Sample.Ping
{
class Program
{
static void Main(string[] args)
{
var inputQueueName = "PingApp";
var connectionString = "amqp://guest:guest@localhost:5672";
var services = new ServiceCollection();
services.AutoRegisterHandlersFromAssemblyOf<Program>();
services.AddSingleton<Producer>();
services.AddRebus(configure => configure
.Transport(t => t.UseRabbitMq(connectionString, inputQueueName))
.Logging(l => l.None())
.UseSharedNothingApproach(builder => builder
.AddWithCustomName<PingEvent1>("PingApp:PingEvent")
.AddWithCustomName<PongEvent1>("PongApp:PongEvent")
//optional
//.AllowFallbackToDefaultConvention()
)
);
using (var provider = services.BuildServiceProvider())
{
provider.UseRebus(rebus =>
{
rebus.Subscribe<PongEvent1>();
//or
//rebus.Advanced.Topics.Subscribe("PongApp:PongEvent");
});
var producer = provider.GetRequiredService<Producer>();
producer.Produce();
}
}
}
}
You can publish messages relying on the type mapping showed above or you can explicitly specify the topic name
_bus.Publish(new PingEvent1 { Foo = "FooValue" }).Wait();
//or
_bus.Advanced.Topics.Publish("PingApp:PingEvent", new { Foo = "FooValue" }).Wait();
//notice the anonymous type being used with no problem
namespace Sample.Pong
{
class Program
{
var inputQueueName = "PongApp";
...
.UseSharedNothingApproach(builder => builder
.AddWithCustomName<PingEvent2>("PingApp:PingEvent")
.AddWithCustomName<PongEvent2>("PongApp:PongEvent")
//optional
//.AllowFallbackToDefaultConvention()
)
...
rebus.Subscribe<PingEvent2>();
//or
//rebus.Advanced.Topics.Subscribe("PingApp:PingEvent");
}
}
using System;
using System.Threading.Tasks;
using Rebus.Handlers;
namespace Sample.Pong
{
public class PingHandler : IHandleMessages<PingEvent2>
{
public Task Handle(PingEvent2 message)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine($"PingHandler received : PingEvent2 {message.Foo}");
Console.ResetColor();
return Task.CompletedTask;
}
}
}
Whell... the it wasen't perfect. In an ideal solution you wouldn't require any headers to deserialize the message on the consumer side. But here we had to add the Topic name as the MessageType.