Dependency injection, inject with parameters
Solution 1
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
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
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
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
A bit late to the party, but you could DI inject a factory that creates and exposes an instance of your provider class.
Related videos on Youtube
Oleksandr Nahirniak
Hi, I'm a software engineer and a technology enthusiast. I started programming 10 years ago and have never stopped. And for the past 7 years, I've been working for the largest outsourcing IT companies in Eastern Europe. I'm experienced in leading teams, designing distributed systems, integrating with 3rd party components, and developing tools for other developers. I write articles and speak at meetups and conferences on subjects like microservices and effective delivery of them in my free time. Nice to meet you!
Updated on December 16, 2021Comments
-
Oleksandr Nahirniak over 2 years
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");
-
Mugen over 4 yearsMy generic solution: gist.github.com/ReallyLiri/c669c60db2109554d5ce47e03613a7a9
-
RBT over 2 yearsRelated post - .NET Core DI, ways of passing parameters to constructor
-
-
Himalaya Garg over 5 yearsSimple and Useful
-
raterus about 5 yearsDon't forget if your service takes other parameters you have registered, you can pass a reference to your service when it is registered. e.g. if "RedisCacheProvider" also required ISomeService, you'd do this: services.AddSingleton<ICacheProvider>(provider => new RedisCacheProvider("myPrettyLocalhost:6379", provider.GetService<ISomeService>()));
-
Steven over 3 years@KévinChalet it would be good if you would specify in your answer that "manually instantiated types" is solely about registering types through
AddSingleton<T>(T)
. Types returned from registered delegates (e.g. usingAddSingleton<T>(Func<IServiceProvider, T>)
) will in fact be disposed of. -
Ak777 almost 3 yearsHow do I go about handling this if I have another implementation of the ICacheProvider?