While reading about IoC/DI containers, I read in a few places (e.g.
here and here and here) that the container should ideally be used only
at startup.
They mean that you configure the container and register all components at application startup (or otherwise very early).
It makes sense, because typically you have a one or a few root objects (e.g. instantiated first by the container) and from there on the container should take of resolving dependencies if all of them are configured correctly.
In other situations you have to request the root objects from the container (e.g. a console or Windows Service application) because there's no way for it to integrate with the platform at startup like it can do for example for ASP.NET WebApi or MVC (well, no way excepting assembly instrumentation).
More exactly, you need to call Resolve
or GetInstance
(or whatever the DI framework supports) for the root objects in these situations.
What about classes that use an instance of a central service
(typically a singleton) which is registered in the container?
All DI containers support per-container lifetime, which is what a singleton basically gives you. So, you can register a singleton instance in the container with a lifetime matching that of the container and then inject that instance where you need it.
EDIT: as it turns out I got this backwards. You have here the options of either registering these classes with the container and let it do the injection, or call Resolve
manually. However, as I said in the comments, some people consider service locator to be an anti-pattern. I think that if you don't abuse it and use it when it's more trouble than worth to register with the container, then do it.
What about classes whose constructors require parameters of types that
are not registered in the container?
I think that's the point of DI. If you want a component to not use DI, then don't register it and instantiate it as usual, via new
.
Otherwise, if unresolved dependencies are detected by the DI container then it will most likely throw. And it should throw so you can see the error and correct it.