Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RabbitMQ with Unity IOC Container in .NET

I am using Unity App Block as my IOC container for my service layer of a WCF project. This works quite well using the Unity.WCF library to plug it into each WCF service.

I recently introduced RabbitMQ into my service layer and I am currently using the "using" blocks to connect and add to the queue. I dont like this though and am looking to use the HierachicalLifetimeManager to create and destroy my connection to RabbitMQ as I need them? Does this sound correct?

I'm looking for a sample of this, or atleast some guidance on the best approach? (e.g. Should I encapsulate the connection and inject into each service as needed? How would I encapsulate RabbitMQ consumer etc?)

like image 890
Neil Hosey Avatar asked May 01 '15 10:05

Neil Hosey


2 Answers

I would advise registering the IConnection as a singleton.

To register the IConnection as a singleton in Unity you would use a ContainerControlledLifetimeManager, e.g.

var connectionFactory = new ConnectionFactory
{
    // Configure the connection factory
};
unityContainer.RegisterInstance(connectionFactory);

unityContainer.RegisterType<IConnection, AutorecoveringConnection>(new ContainerControlledLifetimeManager(),
    new InjectionMethod("init"));

The AutorecoveringConnection instance, once resolved for the first time will stay alive until the owning UnityContainer is disposed.

Because we have registered the ConnectionFactory with Unity, this will automatically be injected into the constructor of AutorecoveringConnection. The InjectionMethod ensures that the first time the AutorecoveringConnection is resolved, the init method is invoked.

As for your question about whether you should abstract away RabbitMQ from your services, my answer would be yes, however I would not simply create an IMessageQueue abstraction. Think about what purpose you are using your message queue for, is it to push statuses? If so, have an IStatusNotifier interface with a concrete implementation for RabbitMQ. If it's to fetch updates, have an IUpdateSource interface with a concrete implementation for RabbitMQ. You can see where I am going with this.

If you create an abstraction for a Message Queue, you are limiting yourself to features only available across all Message Queue implementations. By having a different implementation of IStatusNotifier for different Message Queue implementations, you are able to take advantage of features which are unique to different technologies while also remaining flexible in case completely different technologies are employed in future (e.g. Writing to a SQL database or outputting to a console).

like image 101
Lukazoid Avatar answered Sep 28 '22 06:09

Lukazoid


With RabbitMQ you want your IConnection to be re-used all the time, you don't want it in a "using" block. Here is my IOC binding using Ninject, note the InSingletonScope, this is what you want.

    Bind<IConnection>()
        .ToMethod(ctx =>
                  {
                      var factory = new ConnectionFactory
                      {
                          Uri = ConfigurationManager.ConnectionStrings["RabbitMQ"].ConnectionString,
                          RequestedHeartbeat = 15
                          //every N seconds the server will send a heartbeat.  If the connection does not receive a heardbeat within
                          //N*2 then the connection is considered dead.
                          //suggested from http://public.hudl.com/bits/archives/2013/11/11/c-rabbitmq-happy-servers/
                      };

                      var con = new AutorecoveringConnection(factory);
                      con.init();
                      return con;
                  })
        .InSingletonScope();
like image 25
jhilden Avatar answered Sep 28 '22 07:09

jhilden