Home > Software engineering >  How do I use Dependency Injection in C# .net 6 application to pass in different instances of the sam
How do I use Dependency Injection in C# .net 6 application to pass in different instances of the sam

Time:05-25

I am creating an Azure Function App in Visual Studio with c# and .NET 6.

I have a service I created (CosmosDBService) that implements the interface ICosmosDBService:

public class CosmosDbService : ICosmosDbService
{
    private Container? _container = null;

    public CosmosDbService(
        CosmosClient cosmosDbClient,
        string databaseName,
        string containerName)
    {
        _container = cosmosDbClient.GetContainer(databaseName, containerName);
    }

I want to pass two different instances of this service into the Function App. Each service instance would represent a different container.

How would I set this up in Startup:FunctionsApp class using the FunctionsHostBuilder?

CodePudding user response:

Default DI container does not support named such scenarios so you have next options - either create separate interfaces and implementations (and register/resolve them) for each databaseName-containerName pair or create a factory and use it to generate desired CosmosDbService instance:

public interface ICosmosDbServiceFactory
{
    ICosmosDbService Create(string databaseName, string containerName);
}

class CosmosDbServiceFactory : ICosmosDbServiceFactory
{
    private readonly IServiceProvider _serviceProvider;

    public CosmosDbServiceFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public ICosmosDbService Create(string databaseName, string containerName) => new CosmosDbService(
        _serviceProvider.GetRequiredService<CosmosClient>(),
        databaseName,
        containerName
    );
}

Register it with appropriate lifetime and inject it into corresponding class and use it in the constructor to resolve required ICosmosDbService instances.

CodePudding user response:

You can do this, but I wouldn't recommend it. For instance in your start up if you had the following code:

services.AddSingleton<ICosmosDbService, CosmosDbService>();
services.AddSingleton<ICosmosDbService, OtherCosmosDbService>();

both instances would be registered in the Di container. If you had a class that depends on this interface, the following constructor would result in OtherCosmosDbService being injected:

public class SomeClass {
   private readonly ICosmosDbService _service;
   public SomeClass(ICosmosDbService service){
      _service = service; // This would be OtherCosmosDbService
   }
}

Both would be registered and in this instance, the last one registered "wins". If you wanted to get both then you could change the constructor to this:

public SomeClass(IEnumerable<ICosmosDbService> services){
   // Write logic to handle finding which one you want
}

Honestly, I would go with Guru Stron's suggestion of creating separate interfaces for each container and registering them separately.

  • Related