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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…