Reputation: 2950
As currently there is lack of documentation on DI topic - Dependency Injection. What are pros/cons of using built-in DI over existing solutions like (Ninject, Autofac, StructureMap)? And what are current limitations of default dependency injection (if any)?
Upvotes: 65
Views: 17496
Reputation: 172875
For product development of any reasonably sized application that practice loose coupling and follows the SOLID principles, .NET Core's DI container (MS.DI) is unsuited, because:
ValidateOnBuild
, but the only thing it does is check whether all dependencies of all registrations can be satisfied.Service1
and Service2
that both depend on ILogger
, you might want to inject Service1
with NullLogger
and Service2
with FileLogger
, or you want Service1
to be injected with Logger<Service1>
and Service2
with Logger<Service2>
.The main reason for those limitations to exist is because it's the goal of the built-in container to provide DI capabilities to especially the framework itself, while keeping its feature set to a minimum in the hope that more-mature DI containers would be able to integrate with it. In other words, it tries to act as an Least-Common Denominator (LCD). Because of its LCD function, it can never grow to a full-fledged DI Container that is practical for application development (not without breaking the promise of being an LCD).
If you start with a new and simple project, my advice is to apply Pure DI. This means you hand-wire components inside the Composition Root without using a container and without creating your own DI Container. Instead you resolve your types by plugging in your custom IControllerActivator. Later on, when features such as Auto-Wiring, Auto-Registration and Interception would improve maintainability of your Composition Root, switch to one of the established DI libraries that fits your requirements.
Upvotes: 67
Reputation: 12021
Additionally, can someone help me to 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); }
https://stackoverflow.com/revisions/30681477/8
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/
To explain why it's called scoped a bit more, consider this code:
// app startup
var services = new ServiceCollection();
services.AddScoped<IService, Service>();
var startupServices = services.BuildServiceProvider();
// request init
var requestServices = statupServices.CreateScope().ServiceProvider;
So in ASP.NET HttpContext.RequestServices is created in a similar fashion to above where CreateScope is called at the beginning of the request. But it can be used in contexts outside of ASP.NET in which case scope can have a different meaning than per request.
Upvotes: 7
Reputation: 6757
To answer your first question: it seems that ASP.NET docs were updated and now clearly state what is each type of registration for:
ASP.NET services can be configured with the following lifetimes:
Transient
Transient lifetime services are created each time they are requested. This lifetime works best for lightweight, stateless service.
Scoped
Scoped lifetime services are created once per request.
Singleton
Singleton lifetime services are created the first time they are requested, and then every subsequent request will use the same instance. If your application requires singleton behavior, allowing the services container to manage the service’s lifetime is recommended instead of implementing the singleton design pattern and managing your object’s lifetime in the class yourself.
Instance [pre RTM only!]
You can choose to add an instance directly to the services container. If you do so, this instance will be used for all subsequent requests (this technique will create a Singleton-scoped instance). One key difference between Instance services and Singleton services is that the Instance service is created in ConfigureServices, while the Singleton service is lazy-loaded the first time it is requested.
Updated in RTM
Note that in Asp.Net Core RTM docs Instance was removed. Instance is basically the same thing as Singleton, but they had different initialization semantics (Singleton was lazy loaded). But now there is no AddInstance API, only AddSignleton which can take already created instance.
Upvotes: 6
Reputation: 789
Here it is explained :
Alpha version had this limitations :
If you aren't writing really complicated product default DI container should be sufficient for you. In other cases you can try libraries you already mentioned that have advanced features.
My advice would be to start with the default one and change implementation when(if) you hit something you can't do with it.
Upvotes: 23