How do I manually resolve a type using the ASP.NET Core MVC built-in dependency injection framework?
Setting up the container is easy enough:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddTransient<ISomeService, SomeConcreteService>();
}
But how can I resolve ISomeService
without performing injection? For example, I want to do this:
ISomeService service = services.Resolve<ISomeService>();
There are no such methods in IServiceCollection
.
Best Answer
The
IServiceCollection
interface is used for building a dependency injection container. After it's fully built, it gets composed to anIServiceProvider
instance which you can use to resolve services. You can inject anIServiceProvider
into any class. TheIApplicationBuilder
andHttpContext
classes can provide the service provider as well, via theirApplicationServices
orRequestServices
properties respectively.IServiceProvider
defines aGetService(Type type)
method to resolve a service:There are also several convenience extension methods available, such as
serviceProvider.GetService<IFooService>()
(add ausing
forMicrosoft.Extensions.DependencyInjection
).Resolving services inside the startup class
Injecting dependencies
The runtime's hosting service provider can inject certain services into the constructor of the
Startup
class, such asIConfiguration
,IWebHostEnvironment
(IHostingEnvironment
in pre-3.0 versions),ILoggerFactory
andIServiceProvider
. Note that the latter is an instance built by the hosting layer and contains only the essential services for starting up an application.The
ConfigureServices()
method does not allow injecting services, it only accepts anIServiceCollection
argument. This makes sense becauseConfigureServices()
is where you register the services required by your application. However you can use services injected in the startup's constructor here, for example:Any services registered in
ConfigureServices()
can then be injected into theConfigure()
method; you can add an arbitrary number of services after theIApplicationBuilder
parameter:Manually resolving dependencies
If you need to manually resolve services, you should preferably use the
ApplicationServices
provided byIApplicationBuilder
in theConfigure()
method:It is possible to pass and directly use an
IServiceProvider
in the constructor of yourStartup
class, but as above this will contain a limited subset of services, and thus has limited utility:If you must resolve services in the
ConfigureServices()
method, a different approach is required. You can build an intermediateIServiceProvider
from theIServiceCollection
instance which contains the services which have been registered up to that point:Please note: Generally you should avoid resolving services inside the
ConfigureServices()
method, as this is actually the place where you're configuring the application services. Sometimes you just need access to anIOptions<MyOptions>
instance. You can accomplish this by binding the values from theIConfiguration
instance to an instance ofMyOptions
(which is essentially what the options framework does):Or use an overload for
AddSingleton/AddScoped/AddTransient
:Manually resolving services (aka Service Locator) is generally considered an anti-pattern. While it has its use-cases (for frameworks and/or infrastructure layers), you should avoid it as much as possible.