I was recently on a project where one of the developers decided to use Ninject as the IoC framework. Notice I said framework because it calls INTO your code, whereas a library doesn’t; but I digress.
Anyway, so I added a NinjectModule to the library, added some dependency definitions to it, and committed it to TFS (a whole other problem). All is well.
Well not so well. I get an email a few minutes later questioning why I’m doing such a thing as adding a NinjectModule. I thought for a second–I had gone for a walk around the block to rest my eyes, and began emailing back; the response? Still confusion. It was then and there that I decided that I was wrong about something. I took for granted that “senior engineers” understood why and how Dependency Injection containers worked. I brushed off my frustration and started typing. This is what I wrote, and maybe (I’m not really confident about it) this will help some other person.
Ninject (and other almost all DI frameworks) have an IoC container implementation that’s called something…for Ninject it’s the Kernel. In principle there is a single Kernel (IoC container) at runtime (almost always, but that’s another story).
What a NinjectModule does is act as a registry for dependencies. The principle behind it is encapsulation of higher order implementations, and for components to depend on abstractions. The assembly/component is saying, “Hey you module/component that want to reference me, don’t worry about how “IAmAContract” is implemented (an interface I’m exposing as public), just ask for it, and I’ll make it happen”. The assembly provides a public module (a NinjectModule), which in effect is saying, “Hey I’ve got stuff you want, so add it to your Kernel (IoC Container) without knowing exactly what’s implementing what you want”.
So at runtime in the component that’s one-to-one with the Process, the IoC container is configured, and in Ninject’s case, we’ll tell it to either scan the assemblies in the bin for NinjectModules, or explicitly add them. When this happens, the NinjectModule’s bindings (for this type, use this type) get added to the IoC container, i.e. the Kernel.
In practice this lets us make implementations of a public contract, for example an interface in C#, internal to the owner (in this case, some library we’re building) without the consumer ever having to know or have access to the implementation.