I faced the same problem and want to share how I solved it and why.
As you mentioned, there are two problems. First:
In Asp.Net Core, how can I register these services and solve them at runtime based on some key?
So what are our options? People offer two:
Is a factory template the only option here?
In fact, both options are factories, because each IoC container is also a factory (very customizable and complex). And it seems to me that the other options are also variations of the factory pattern.
So which option is better? Here, I agree with @Sock, who suggested using a custom factory, and that is why.
First, I always try to avoid adding new dependencies when they are not really needed. Therefore, I agree with you on this issue. Moreover, using two DI structures is worse than creating a custom factory abstraction. In the second case, you need to add a new package dependency (for example, Unity), but depending on the new factory interface, here is less evil. I believe that the basic idea of ASP.NET Core DI is simplicity. It supports a minimal set of functions following the KISS Principle . If you need an additional function, do DIY or use the appropriate Plungin , which implements the desired function (Open Closed Principle).
Secondly, often we need to introduce many named dependencies for a single service. In the case of Unity, you may need to provide names for constructor parameters (using the InjectionConstructor ). This registration uses reflection and some intelligent logic to guess the arguments for the constructor. It can also lead to runtime errors if registration does not match the constructor arguments. On the other hand, when using your own factory, you have full control over how to provide constructor parameters. This is more readable and resolved at compile time. KISS principle .
The second problem:
How can _serviceProvider.GetService () enter an appropriate connection string?
First, I agree with you that depending on new things like IOptions (and therefore on the Microsoft.Extensions.Options.ConfigurationExtensions package), this is not a good idea. I saw some discussing the issue of IOptions , where there were different opinions about its benefits. Again, I try to avoid adding new dependencies when they are not really needed. Is it really necessary? I think no. Otherwise, each implementation would have to depend on it without any obvious need for this implementation (for me, this looks like an ISP violation, where I also agree with you). This is also true depending on the factory, but in this case it can be avoided.
The ASP.NET Core DI kernel provides very good overload for this purpose:
var mongoConnection = //... var efConnection = //... var otherConnection = //... services.AddTransient<IMyFactory>( s => new MyFactoryImpl( mongoConnection, efConnection, otherConnection, s.GetService<ISomeDependency1>(), s.GetService<ISomeDependency2>())));