Resolution of instances using ASP.NET Core DI

How to manually resolve a type using the ASP.NET Core MVC embedded I / O?

Setting up the container is quite simple:

public void ConfigureServices(IServiceCollection services) { // ... services.AddTransient<ISomeService, SomeConcreteService>(); } 

But how can I resolve ISomeService without performing an injection? For example, I want to do this:

 ISomeService service = services.Resolve<ISomeService>(); 

There are IServiceCollection such methods in IServiceCollection .

+200
c # dependency-injection asp.net-core asp.net-core-mvc
Sep 08 '15 at 13:53 on
source share
6 answers

The IServiceCollection interface IServiceCollection used to build a dependency injection container. After a complete build, it is assembled into an instance of IServiceProvider that can be used to resolve services. You can embed IServiceProvider in any class. IApplicationBuilder and HttpContext can provide a service provider through ApplicationServices or RequestServices respectively.

IServiceProvider defines GetService(Type type) to enable the service:

 var service = (IFooService)serviceProvider.GetService(typeof(IFooService)); 

There are also several convenient extension methods, such as serviceProvider.GetService<IFooService>() (add using for Microsoft.Extensions.DependencyInjection ).

Enabling Services Inside the Launch Class

Dependency Injection

The runtime can embed services in the constructor of the Startup class, such as IHostingEnvironment , IConfiguration and IServiceProvider . Please note that this service provider is an instance created at the hosting level and contains only services for launching the application.

Services can also be added to the Configure() method. You can add an arbitrary parameter list after the IApplicationBuilder parameter. You can also add your own services that are registered in the ConfigureServices() method; here they will be decided not by the hosting service provider, but by the application service provider.

 public void Configure(IApplicationBuilder app, IFooService fooService) { // ... } 

However, the ConfigureServices() method does not allow services to be deployed; it accepts the IServiceCollection argument of IServiceCollection . This is the method in which you configure your application dependency injection container. You can use the services added to the startup constructor here. For example:

 public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public void ConfigureServices(IServiceCollection services) { // Use Configuration here } 

Manual dependency resolution

If you want to enable services manually, you can IServiceProvider let the runtime implement the IServiceProvider instance in the constructor or use the ApplicationServices provided by IApplicationBuilder in IApplicationBuilder Configure() :

 public Startup(IServiceProvider serviceProvider) { var hostingEnv = serviceProvider.GetService<IHostingEnvironment>(); } 

or

 public void Configure(IApplicationBuilder app) { var serviceProvider = app.ApplicationServices; var hostingEnv = serviceProvider.GetService<IHostingEnvironment>(); } 

However, if you need to enable services in the ConfigureServices() method, you need a different approach. You can create an intermediate IServiceProvider from an IServiceProvider instance that contains the services that are registered so far:

 public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IFooService, FooService>(); // Build the intermediate service provider var sp = services.BuildServiceProvider(); var fooService = sp.GetService<IFooService>(); } 

To do this, you need the Microsoft.Extensions.DependencyInjection package.

Please pay attention:
As a rule, you should not allow services inside the ConfigureServices() method, since this is where you configure application services. Sometimes you just need access to some IOptions<MyOptions> . You can do this, IConfiguration values ​​from an IConfiguration instance with an MyOptions instance (which, in essence, does the parameter infrastructure):

 public void ConfigureServices(IServiceCollection services) { var myOptions = new MyOptions(); Configuration.GetSection("SomeSection").Bind(myOptions); } 

Manually authorizing services (aka Service Locator) is usually called an anti-pattern . Although it has its own use cases (for frameworks and / or infrastructural levels), you should avoid it as much as possible.

+327
Sep 08 '15 at 15:30
source share

IServiceProvider instance IServiceProvider enables the use of the IServiceProvider interface:

Dependency Resolution in Startup.ConfigureServices

 public void ConfigureServices(IServiceCollection services) { services.AddTransient<IMyService, MyService>(); var serviceProvider = services.BuildServiceProvider(); var service = serviceProvider.GetService<IMyService>(); } 

Dependency Resolution in Startup.Configure

 public void Configure( IApplicationBuilder application, IServiceProvider serviceProvider) { // By type. var service1 = (MyService)serviceProvider.GetService(typeof(MyService)); // Using extension method. var service2 = serviceProvider.GetService<MyService>(); // ... } 

Using Runtime Injected Services

Some types can be entered as method parameters:

 public class Startup { public Startup( IHostingEnvironment hostingEnvironment, ILoggerFactory loggerFactory) { } public void ConfigureServices( IServiceCollection services) { } public void Configure( IApplicationBuilder application, IHostingEnvironment hostingEnvironment, IServiceProvider serviceProvider, ILoggerFactory loggerfactory, IApplicationLifetime applicationLifetime) { } } 

Dependency resolution in controller actions

 [HttpGet("/some-action")] public string SomeAction([FromServices] IMyService myService) => "Hello"; 
+69
Sep 08 '15 at 14:15
source share

If you are creating an application with a template, you will have something like this in the Startup class:

 public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddApplicationInsightsTelemetry(Configuration); services.AddMvc(); } 

Then you can add dependencies there:

 services.AddTransient<ITestService, TestService>(); 

If you want to access ITestService on your controller, you can add IServiceProvider to the constructor, and it will be entered:

 public HomeController(IServiceProvider serviceProvider) 

Then you can enable the added service:

 var service = serviceProvider.GetService<ITestService>(); 

Please note that in order to use the generic version you need to include a namespace with extensions:

 using Microsoft.Extensions.DependencyInjection; 



ITestService.cs

 public interface ITestService { int GenerateRandom(); } 

TestService.cs

 public class TestService : ITestService { public int GenerateRandom() { return 4; } } 

Startup.cs (ConfigureServices)

 public void ConfigureServices(IServiceCollection services) { services.AddApplicationInsightsTelemetry(Configuration); services.AddMvc(); services.AddTransient<ITestService, TestService>(); } 

HomeController.cs

 using Microsoft.Extensions.DependencyInjection; namespace Core.Controllers { public class HomeController : Controller { public HomeController(IServiceProvider serviceProvider) { var service = serviceProvider.GetService<ITestService>(); int rnd = service.GenerateRandom(); } 
+13
Jul 06 '16 at 22:59
source share

If you just need to resolve one dependency in order to pass it to the constructor of another dependency that you register, you can do this.

Suppose you have a service that accepts a string and an ISomeService.

 public class AnotherService : IAnotherService { public AnotherService(ISomeService someService, string serviceUrl) { ... } } 

When you sign up for Startup.cs, you will need to do the following:

 services.AddScoped<IAnotherService>(ctx => new AnotherService(ctx.GetService<ISomeService>(), "https://someservice.com/") ); 
+1
Apr 14 '19 at 20:49
source share

In this way, you can inject dependencies into attributes such as AuthorizeAttribute.

 var someservice = (ISomeService)context.HttpContext.RequestServices.GetService(typeof(ISomeService)); 
0
Apr 04 '19 at 10:56
source share
 public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddDbContext<ConfigurationRepository>(options => options.UseSqlServer(Configuration.GetConnectionString("SqlConnectionString"))); services.AddScoped<IConfigurationBL, ConfigurationBL>(); services.AddScoped<IConfigurationRepository, ConfigurationRepository>(); } 
-four
Nov 25 '17 at 19:33
source share



All Articles