There is a difference between having multiple container libraries in the same solution vs. the same application, since a solution can consist of multiple runnable applications.
All components should be wired in the application's start-up path, a.k.a. the Composition Root:
A Composition Root is a (preferably) unique location in an application where modules are composed together.
Together with the use of Constructor Injection, the Composition Root pattern keeps your application completely loosely coupled, and keeps your application code decoupled from your DI Container.
According to the Composition Root pattern, no other parts of an application should therefore depend on a DI Container. The fact that the libraries that you use do, is problematic, because this forces you into a certain DI Container. A better solution is to make the libraries DI-friendly.
There are a few downsides to having multiple container libraries in the same solution:
- You have to learn two different DI Container libraries, each with their limitations and quirks
- Each library comes with its own risk to needing to be replaced when development stops.
On top of that, there are a few downsides to using multiple container libraries in the same application:
- Complexities can arise when a single object graph is constructed of application components that come from different containers. It can be hard to visualize object graphs and verify them for correctness.
- If some component is resolved from both containers, it could lead to Torn Lifestyles
That's not to say that you should never have multiple containers in the same solution or application. For instance, you could have two containers as a temporary solution, because you are moving from one library to the next, but a big bang migration is too much work. Ideally, you would in that case migrate one application at the time, but even that could be too much to chew off at once.
Another common scenario where having two containers is fine, is when the application framework you are running is using a DI Container internally to build up its services. Common examples of these frameworks are ASP.NET Core and NServiceBus. In that case, to make the distinction clear, I typically talk about the framework's configuration system instead of its internal container, since that's what it basically is. It being a container, is an implementation detail.
In that case you can leave the built-in 'configuration system' as-is to resolve framework components, and use your DI Container of choice to build object graphs of application components.