The core of a DI container is generally extremely simple — objects are constructed by scanning collections of registered dependency types for matches and constructing them with the same process before passing them on. It has a recursive structure that I would even call elegant.
Dependency Injection Frameworks have the same issues: - understanding what is going on is harder than injecting objects by hand. - you have limited control over object lifetimes (when objects are created and disposed). Permanent, scoped and transient might be enough most of the time for a web service, but as soon as you fire off tasks that can outlive the requests or when you use it in different circumstances like UI it’s getting a problem.