Home > Software engineering >  Dependency injection not working when overloading AddTransient with required classes in .NET Core
Dependency injection not working when overloading AddTransient with required classes in .NET Core

Time:01-15

In startup class we added:

services.AddTransient<ITasksService, TasksService>(provider => MultiTenentDB<TeamService>(provider));

private T MultiTenentDB<T>(IServiceProvider provider)
{
        IServiceScope scope = provider.CreateScope();
        AppTenant appTenent = scope.ServiceProvider.GetService<AppTenant>();

        if (appTenent == null)
            throw new InvalidOperationException("Organization id required");

        string connectionString = string.Format(appTenent.MongoDbServer.ConnectionString);
        MongoClient mongoClient = new MongoClient(connectionString);
        string database = "";

        if (_env.IsProduction())
        {
            database = appTenent.MongoDbServer.DatabaseProd;
        }
        else  
        {
            database = appTenent.MongoDbServer.Database;
        }

        return (T)Activator.CreateInstance(typeof(T), new object[] { mongoClient, database });
    }

In TaskService:

public class TasksService : ITaskService
{
    public readonly ISendEmailService _SendemailService;
    public readonly IEmailBodyService _emailBodyService;
    private IMongoCollection<TasksModel> _task;

    public TasksService(IMongoClient client, string database) 
    {
        _database = client.GetDatabase(database);
        _task = _database.GetCollection<TasksModel>("Tasks");
    }

    public TasksService(  ISendEmailService SendemailService, IEmailBodyService emailBodyService)
    {
        _SendemailService = SendemailService;
        _emailBodyService = emailBodyService;
    }
} 

TasksService( ISendEmailService SendemailService, IEmailBodyService emailBodyService)

is not firing due to overloading of the transient in the startup class. How to fire both the constructors or any other solution?

CodePudding user response:

Instead of using Activator.CreateInstance, you should instead use ActivatorUtilities.CreateInstance, which allows you to inject services from the provider.

That way, you can have a single constructor:

public TasksService(  ISendEmailService SendemailService, IEmailBodyService emailBodyService, IMongoClient client, string database)
{
    _SendemailService = SendemailService;
    _emailBodyService = emailBodyService;
    
    _database = client.GetDatabase(database);
    _task = _database.GetCollection<TasksModel>("Tasks");
}

and then in MultiTenentDB<T> :

return ActivatorUtilities.CreateInstance<T>(provider, mongoClient, database);

ActivatorUtilities.CreateInstance will call the appropriate constructor, with services ISendEmailService and IEmailBodyService injected from the service provider, while IMongoClient client and string database are the arguments of the call.

  •  Tags:  
  • Related