How to use dependency injection in enterprise projects
architecture, c#, dependency-injection, inversion-of-control
Solution
First of all, Dependency Injection is a design pattern that does not require a container. The DI pattern states:
Dependency injection is a software design pattern that allows a choice of component to be made at run-time rather than compile time
Take for example Guice (java dependency injection framework), in Java Guice is a DI framework but it is not a container itself.
Most of the DI tools in .Net are actually containers, so you need to populate the container in order to be able to inject the dependency
I do not like the idea to have to register every component every time in a container, I simply hate that. There are several tools that help you auto register components based on conventions, I do not use Unity, but I can point you for example to Ninject or AutoFac
I am actually writing a small utility to auto register components based on conventions using practically any DI tool, it is still in dev phase
About your questions:
Should there be a "general container" that can be used for bootstrapping, accessible as a Singleton?
The answer is yes, (there's a tool to abstract the DI tool used, it is called ServiceLocator) that's how DI tools work, there is a static container available to the application, however, it is not recommended to use it inside the domain objects to create instances, that's considered an anti-pattern
BTW I have found this tool really useful to register components at runtime:
http://bootstrapper.codeplex.com/
Should a container be passed around, where all instances can RegisterInstance?
No. that would violate the law of Demeter. If you decide to use a container is better to register the components when the application starts
How can the container be made accessible when needed
Well using the Common Service Locator you could use it anywhere in your application, but like I said, it is not recommended to use it inside the domain objects to create the required instances, instead, inject the objects in the constructor of the object and let the DI tool to automatically inject the correct instance.
Now based on this:
Constructor injection seems false, controverse of being the standard way, you have to pass down interfaces from a component level to the very down where it is used right on startup, or a reference is hold ending up in a "know where you live" antipattern
Makes me think that you are not writing unit tests heavily for your application which is bad. So my suggestion is, before choosing between which DI tool you are going to use, or before taking all the answers you get to this question into consideration, refer to the following links which are focus on one thing: Write clean testable code, this is by far the best source you could get to answer yourself your own question
Clean Code talks:
http://www.youtube.com/watch?v=wEhu57pih5w&feature=player_embedded
http://www.youtube.com/watch?v=RlfLCWKxHJ0&feature=player_embedded
Articles
http://misko.hevery.com/2010/05/26/do-it-yourself-dependency-injection/
http://misko.hevery.com/code-reviewers-guide/
Previous link in PDF http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf
The following links are super highly recommended
http://misko.hevery.com/2008/09/30/to-new-or-not-to-new/
http://www.loosecouplings.com/2011/01/how-to-write-testable-code-overview.html
Problem
Imagine you have an application with several hundreds of classes implementing dozens of "high level" interfaces (meaning component level). Is there a recommend way of doing dependecy injection (like with unity). Should there be a "general container" that can be used for bootstrapping, accessible as a Singleton? Should a container be passed around, where all instances can RegisterInstance? Should everything be done by RegisterType somewhere in the startup? How can the container be made accessible when needed. Constructor injection seems false, controverse of being the standard way, you have to pass down interfaces from a component level to the very down where it is used right on startup, or a reference is hold ending up in a "know where you live" antipattern. And: having a container "available" may bring developers to the idea of resolving server components in client context. how to avoid that? Any discussion welcome! edit for clarification I figured out a somewhat realworld example to have a better picture of what problems i see. lets imagine the application is a hifi system. the system has cd player (integrated in a cd-rack) and an usb port (integrated in an usb rack) to play music from. now, the cd player and the usb port shall be able to play mp3 music. i have an mp3 decoder somewhere around, which is injectable. now i start the hifi system. there is no cd inserted yet and no usb stick pluged in. i do not need a mp3 decoder now. but with constructor injection, i have to already inject the dependency into the cd rack and the usb rack. what if i never insert a mp3 cd or an mp3 usb stick? shall i hold an reference in the cd rack, so when an mp3 cd is inserted, i have a decorder on hand? (seems wrong to me) the decoder is needed in a subsystem of the cd rack, which is only started if a mp3 gets inserted. now i have no container in the cd rack, what about constructor injection here?