user2382627
user2382627

Reputation:

Resolve .net core injection

I have an interface IRabbitSender and the implementation RabbitSender

public class RabbitSender : IRabbitSender(){
     
   public RabbitSender(string connection, string queue){
          
   }

   public void Send (object info){ // send message to specific queue }

}

I need different instances of the RabbitSender that will send information for different queues/connections. But I only know which instance choose in runtime.

How can I do the DI? Actually, I have this, but I don't know how to distinct both and how to resolve the dependency in runtime.

 services.AddTransient<IRabbitSender>(s => new RabbitSender(connection1, queueName1));
 services.AddTransient<IRabbitSender>(s => new RabbitSender(connection2, queueName1));

Upvotes: 0

Views: 66

Answers (2)

Steven
Steven

Reputation: 172875

There are several approaches to take here. Here are two to consider.

  1. Consider making the interface generic:
IRabbitSender<TMessage>

This allows the consumer specifying which message to send, and in your configuration you can map message types to queues (tip: try keeping message names and queue names in sync as a convention; that drastically simplifies your life):

// Handy extension method
public static AddSender<TMessage>(
    this IServiceCollection services, string con, string queue)
{
    services.AddSingleton<IRabbitSender<TMessage>(new RabbitSender(con, queue);
}

// Registrations
services.AddSender<ShipOrder>(connection1, queueName1);
services.AddSender<CancelOrder>(connection2, queueName1);
  1. Inject the full list queues into RabbitSender

Another option is to inject the mapping of messages types to queue information into RabbitSender. For instance:

public class RabbitSender : IRabbitSender {
   private Dictionary<Type, (string connection, string queue)> senders;
   public RabbitSender(Dictionary<Type, (string connection, string queue)> senders){
       this.senders = senders;
   }

   public void Send(object info) {
       var queueInfo = this.senders[info.GetType];
       // TODO: Use queue info to send message to a queue
   }
}

// Registration
servies.AddSingleton<IRabbitSender>(new RabbitSender(new Dictionary
{
    { typeof(ShipOrder), (connection1, queueName1) }
    { typeof(CancelOrder), (connection2, queueName1) }
}

Upvotes: 1

OlegI
OlegI

Reputation: 6020

You need to new up your RabbitSender class when you register instance it should be unique to. For example:

services.AddTransient<IRequireUniqueRabbit>(_ => {
   return new RequireUniqueRabbit(new RabbitSender(connString1, queue1))
});

services.AddTransient<IRequireUniqueRabbit2>(_ => {
   return new RequireUniqueRabbit2(new RabbitSender(connString2, queue2))
});

PS: Think about how you register classes holding the RabbitMQ connection, if you register them as transient or scoped they will dispose rabbitMQ connection each time they are disposed, most likely you want to avoid that

Upvotes: 0

Related Questions