Dependency injection, inject with parameters

C#asp.net CoreDependency Injectionasp.net Core-Mvc

C# Problem Overview


I'm using vNext implementation of DI. How to pass parameters to constructor? For example, i have class:

public class RedisCacheProvider : ICacheProvider
{
    private readonly string _connectionString;

    public RedisCacheProvider(string connectionString)
    {
        _connectionString = connectionString;
    }
    //interface methods implementation...
}

And service register:

services.AddSingleton<ICacheProvider, RedisCacheProvider>();

How to pass parameter to constructor of RedisCacheProvider class? For example for Autofac:

builder.RegisterType<RedisCacheProvider>()
       .As<ICacheProvider>()
       .WithParameter("connectionString", "myPrettyLocalhost:6379");

C# Solutions


Solution 1 - C#

You can either provide a delegate to manually instantiate your cache provider or directly provide an instance:

services.AddSingleton<ICacheProvider>(provider => new RedisCacheProvider("myPrettyLocalhost:6379"));

services.AddSingleton<ICacheProvider>(new RedisCacheProvider("myPrettyLocalhost:6379"));

Please note that the container will not explicitly dispose of manually instantiated types, even if they implement IDisposable. See the ASP.NET Core doc about Disposal of Services for more info.

Solution 2 - C#

If the constructur also has dependencies that should be resolved by DI you can use that:

public class RedisCacheProvider : ICacheProvider
{
    private readonly string _connectionString;
    private readonly IMyInterface _myImplementation;

    public RedisCacheProvider(string connectionString, IMyInterface myImplementation)
    {
        _connectionString = connectionString;
        _myImplementation = myImplementation;
    }
    //interface methods implementation...
}

Startup.cs:

services.AddSingleton<IMyInterface, MyInterface>();
services.AddSingleton<ICacheProvider>(provider => 
    RedisCacheProvider("myPrettyLocalhost:6379", provider.GetService<IMyInterface>()));

Solution 3 - C#

You can use :

 services.AddSingleton<ICacheProvider>(x =>
      ActivatorUtilities.CreateInstance<RedisCacheProvider>(x, "myPrettyLocalhost:6379"));

Dependency Injection : ActivatorUtilities will inject any dependencies to your class.

Here is the link to the MS docs: Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance

Also: See @poke's answer here for more information. Basically it pulls from the provided services and any other params you pass, like a composit constructor.

Solution 4 - C#

You can use something like the example code below.

Manager class:

public class Manager : IManager
{
    ILogger _logger;
    IFactory _factory;
    public Manager(IFactory factory, ILogger<Manager> logger)
    {
        _logger = logger;
        _factory = factory;
    }
}

Startup.cs class:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IFactory, Factory>(sp =>
    {
        var logger = sp.GetRequiredService<ILogger<Factory>>();
        var dbContext = sp.GetRequiredService<MyDBContext>();
        return new Factory(dbContext, logger);
    });
    services.AddTransient<IManager, Manager>(sp =>
    {
        var factory = sp.GetRequiredService<IFactory>();
        var logger = sp.GetRequiredService<ILogger<Manager>>();
        return new Manager(factory, logger);
    });
}

You can read the full example here: DI in Startup.cs in .Net Core

Solution 5 - C#

A bit late to the party, but you could DI inject a factory that creates and exposes an instance of your provider class.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionOleksandr NahirniakView Question on Stackoverflow
Solution 1 - C#Kévin ChaletView Answer on Stackoverflow
Solution 2 - C#feeeperView Answer on Stackoverflow
Solution 3 - C#Henry HuangalView Answer on Stackoverflow
Solution 4 - C#Rahul JhaView Answer on Stackoverflow
Solution 5 - C#Eric JohanssonView Answer on Stackoverflow