Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
875 views
in Technique[技术] by (71.8m points)

dependency injection - Why would one use a third-party DI Container over the built-in ASP.NET Core DI Container?

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)?

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);
}
Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

For product development of any reasonably sized application that practice loose coupling and follows the SOLID principles, .NET Core's DI container is unsuited, because:

  • It doesn't help you in verifying your configuration, making it really hard to diagnose problems that come from common misconfigurations. In a reasonably sized application, it's actually quite hard to spot these mistakes yourself. UPDATE: Version 3 of MS.DI now contains a feature called ValidateOnBuild, but the only thing it does is check whether all registrations can be created.
  • It is impossible to apply Cross-Cutting Concerns using interceptors or decorators in a maintainable fashion. This makes maintaining any reasonably sized application really expensive. UPDATE: There are several third-party libraries that try to fill the gap, but due to limitations in MS.DI, they can't completely fill this gap (e.g. decorate open-generic registrations, ensure disposal of decorated instances, etc.)
  • Although it supports mapping of open-generic abstractions to open-generic implementations, its implementation is rather naive and is unable to work with generic types with type constraints, more complex generic type mappings, and variance.
  • It is impossible to make conditional/contextual registrations, in such way that registrations only get injected to a certain set of consumers, while using Auto-Wiring. e.g. when having two components 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-fletched 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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...