These are some definitions:
public interface IClassA
{
}
public class ClassA : IClassA
{
public ClassA()
{
Init();
}
private void Init()
{
Console.WriteLine("Hello!!!");
}
}
public class ClassB
{
private IClassA _classA;
public ClassB(IClassA classA)
{
this._classA = classA;
}
}
If I build the service provider, the singleton instance will be created twice or more after I add more serivces into the ioc container and get them.
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.TryAddSingleton<IClassA,ClassA>();
ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
serviceProvider.GetRequiredService<IClassA>();
serviceCollection.TryAddSingleton<ClassB>();
serviceProvider = serviceCollection.BuildServiceProvider();
serviceProvider.GetRequiredService<ClassB>();
The output is:
Hello!!!
Hello!!!
It means the instance ClassA has been created twice. I want to use the ServiceProvider after I add some services into the ioc container at the stage one. I want to add some services into the container at the stage two and get some services. However, how can I make sure the service that is singleton will be created once still after I get my services at stage two.
As each IServiceProvider
keeps track of its own services separately, using the approach of registering the type will not work properly as each provider will end up instantiating the singleton, leading to 2 distinct instances as you saw.
If you really want to have 2 providers (a bad idea in general), you could workaround this problem by passing the instance to the container:
var classA = new ClassA();
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<IClassA>(classA);
ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
serviceProvider.GetRequiredService<IClassA>();
serviceCollection.TryAddSingleton<ClassB>();
serviceProvider = serviceCollection.BuildServiceProvider();
serviceProvider.GetRequiredService<ClassB>();
When resolving anything from either provider, it will not attempt to instantiate the type since you are providing the instance explicitly.
This is however a fairly hacky approach and I would not recommend it unless it really was your last option.