Why use a third-party DI container on top of the embedded ASP.NET Core DI container?

Since there is currently a lack of documentation on the topic of DI - Dependency Injection . What are the pros / cons of using embedded DI on top of existing solutions like (Ninject, Autofac, StructureMap)? And what are the current limitations of dependency injection by default (if any)?

Also, can someone help me understand what is the difference between these registrations?

public void ConfigureServices(IServiceCollection services) { services.AddTransient<IService, Service>(); services.AddScoped<IService, Service>(); services.AddSingleton<IService, Service>(); services.AddInstance(service); } 
+40
dependency-injection asp.net-core
Jun 06 '15 at 10:01
source share
4 answers

The .NET Core DI container is not suitable for developing any application of a reasonable size that uses loose coupling and follows SOLID principles, because:

  • This will not help you verify your configuration, which makes it very difficult to diagnose problems that arise due to common incorrect settings. In applications of a reasonable size, it is actually quite difficult to detect these errors yourself.
  • You cannot apply cross-cutting issues using interceptors or decorators in a supported manner. This makes maintaining any reasonable size application really expensive.
  • Although it supports the mapping of open universal abstractions to open universal implementations, its implementation is rather naive and cannot work with universal types with type restrictions, more complex comparisons of universal types and dispersion.
  • It is impossible to make conditional / contextual registration in such a way that when using Auto-Wiring registrations are introduced only to a certain circle of consumers. for example, if you have two components Service1 and Service2 , which both depend on ILogger , you can inject Service1 with NullLogger and Service2 with FileLogger , or you want Service1 to be introduced with Logger<Service1> and Service2 with Logger<Service2> .

The main reason for the existence of these restrictions is that the purpose of the built-in container is to provide DI capabilities especially to the platform itself while maintaining a minimum set of its functions in the hope that more mature DI containers will be able to integrate with this. In other words, it acts as the smallest common denominator (LCD). Thanks to the LCD function, it can never turn into a full-fledged DI container, which will be practical for application development.

If you are starting with a new and simple project, I advise you to use Pure DI (which means manual components inside the root of the composition without using a container) and enable your types by connecting your own IControllerActivator . Later, when features such as automatic registration and interception will improve the usability of your composition root, switch to one of the installed DI libraries that meets your requirements.

+46
Jun 06 '15 at 11:24
source share

It explains:

  • Transient - a new instance is created every time
  • Scoped - one instance is created inside the current area. This is equivalent to Singleton in the current area.
  • Singleton - One instance is created and it acts as a singleton
  • Instance - Specifies a specific instance. You are responsible for your initial creation.

The alpha version had the following limitations:

  • It only supports constructor injection
  • It can only allow types with one and only one public constructor.
  • It does not support advanced features (for example, for stream area or automatic detection).

If you are not writing a really complex product, then the DI container should be enough for you. In other cases, you can try libraries that you already mentioned that have advanced features.

My advice would be to start with the default and change the implementation when (if) you hit what you cannot do with it.

+18
Jun 06 '15 at 11:03
source share

What is the difference between these registrations?

  • Transient - created every time it is retrieved
  • Scoped - created once for each HTTP request and will be available for the life of the http request
  • Singleton - created instance once and will be available for the entire life of your application.
  • Instance is the equivalent of singleton, except that you provide an instance of the object instead of the framework that creates the instance

Source: http://www.khalidabuhakmeh.com/asp-vnext-dependency-injection-lifecycles , http://dotnetliberty.com/index.php/2015/10/15/asp-net-5-mvc6-dependency- injection-in-6-steps /

+6
Nov 10 '15 at 23:21
source share

To answer your first question: it seems that ASP.NET docs have been updated and now clearly indicate that each type of registration is for:

ASP.NET services can be configured with the following lifetimes:

Transient

Temporary lifetime services are created each time they are requested. This lifelong job is best suited for lightweight, attack-free service.

Scoped

Custom lifetime services are created once for each request.

Singleton

Singleton lifecycle services are created the first time they are requested, and then each subsequent request will use the same example. If your application requires monotonous behavior, it is recommended that you use the service container to manage the life of the service instead of implementing a singleton design pattern and managing your life in class.

Instance [only up to RTM!]

You can add an instance directly to the services container. If you do this, this instance will be used for all subsequent requests (this method will create a Singleton instance). One key difference between instance services and Singleton services is that the instance service is created in ConfigureServices, and the Singleton service is loaded the first time the first time it is requested.




Updated in RTM

Notice that the Asp.Net Core RTM docs instance is deleted. The instances are basically the same as Singleton, but they had different initialization semantics (Singleton was lazy loaded). But now there is no AddInstance API, only AddSignleton, which can accept an already created instance.

+5
Feb 14 '16 at 13:56
source share



All Articles