Is there a way to add services outside Startup class. In other words can we get access to ServiceCollection for current request outside Startup?
There's a typical scenario in IoC when you have a factory which creates child container, register additional services depending on input parameters (i. e. query parameter in case of Web Api) and then resolve a specific service. This workflow it supported by every IoC tool I've ever worked with but I don't see a way to do this via ASP.NET Core Dependency Injection. It seems like every sample I can find adds services inside Startup class.
Even though im guilty myself of mis-using the IOC container as factory method or repository. it has not made for this, and is kind-of an anti pattern.
So: Microsoft tries to protect against this by: Splitting the IOC container in a IServiceCollection
(the builder) and the IServiceProvider
(the resolver).
In the Microsoft.AspNetCore.Hosting.StartupBase
:
public virtual IServiceProvider ConfigureServices(IServiceCollection services)
{
return services.BuildServiceProvider();
}
Turns the IServiceCollection
into a IServiceProvider
.
The default implementation does not provide on the fly adding of new dependencies.
If you want this, you should use another Container, or make your own implementation that falls back to the default container.
I'm not sure what the exact reasons are behind this. But i will list a few:
string key
name (like a factory method). Then your code is tightly coupled to the registration of this key. (and not loosely coupled).public class MyServiceProviderWrapper : IServiceProvider
{
private readonly IServiceProvider _msDefaultProvider;
public MyServiceProviderWrapper(IServiceProvider msDefaultProvider)
{
_msDefaultProvider = msDefaultProvider;
}
public object GetService(Type serviceType)
{
//I can return my own implementation here:
//If(myRegistrations.contains(serviceType)) myRegistrations.get(serviceType)
//fallback to microsofts default container:
return _msDefaultProvider.GetService(serviceType);
}
}
public class MyStartup : Microsoft.AspNetCore.Hosting.StartupBase
{
public override IServiceProvider ConfigureServices(IServiceCollection services)
{
// We build the di container.
// we could save MyServiceProviderWrapper on a static property for later use. (or turn itself into a singleton).
return new MyServiceProviderWrapper(base.ConfigureServices(services));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With