Dependency Injection makes developers' life easier!
What is Inversion of Control (IoC)?
The basic idea of inversion of control is:
Decoupling rules from implementation
What is Dependency Injection (DI)?
The basic idea of dependency injection is:
If you have an object that interacts with other objects
the responsibility of finding a reference to those objects at run time
is moved outside of the object itself
the responsibility of finding a reference to those objects at run time
is moved outside of the object itself
Martin Fowler defines dependency injection as "A software design pattern that takes advantage of plugins to handle the interaction between components so that using different implementations in different deployments and assembling these plugins into an application is possible".
In the following example class Foo is interacting with class Bar (Foo depends on Bar to fulfill a responsibility).In this case, Foo creates a new Instance of Bar and invokes its method.
On the other side, In the following example the responsibility of getting a reference to an implementation of type IBar is moved outside of Foo. In this case, IBar has been injected into Foo as a dependency, via the constructor (It is also possible to inject dependencies via a property or even a regular method).
How DI helps you to develop cleaner codes?
Dependency Injection is an evolution of the "Factory Pattern" and can be done by hand or using a framework. It is basically an automated way to initialize a graph of objects which has the following benefits:
- Facilitates the writing of testable code.
- Leads to creating loosely-coupled and highly-cohesive code and makes your code easier to change (Nate Kohari)
- Reduction of boilerplate code in the application objects since all work to initialize or set up dependencies is handled by a provider component.
What is a Bootstrapper?
A program that bootstraps itself is one that begins with an extremely trivial operation and then uses that to continue the start-up process internally. In a strict sense, the program does need help for the very first step but once that happens it doesn't need any external help.
Traditional IoC solutions typically use a bootstrapper to configure components explicitly. The bootstrapper component has its own dependencies, but they're isolated to a single place within the application. This is usually a container that can be passed around; it can create classes while passing in the required dependencies, or it can be queried to return an implementation for an interface.
Generally speaking, A bootstrapper in any application can be considered the entry point for running the application that is used to configure and initialize application's shell, modules as well as the IoC container.
As an example the following is the Prism bootstrapper definition:
"The bootstrapper is responsible for the initialization of an application built using the Composite Application Library. By using a bootstrapper, you have more control of how the Composite Application Library components are wired up to your application." (MSDN)
Convention over configuration
Convention over configuration (also known as coding by convention) is a software design paradigm which seeks to decrease the number of decisions that developers need to make, gaining simplicity, but not necessarily losing flexibility (Wikipedia).
Convention over configuration takes the stance that the configuration of DI framework is actually part of application, and should not be publicly configurable. However, if certain bindings are required to be configurable, then explicit configuration based on app.config or XML can be used to do that.
Having bindings in code saves you from the verbosity of XML, and gives you type-safety, refactorability, and intellisense. As an example Ninject takes Convention over configuration approach.
.NET DI frameworks
See Scott Hanselman's "List of .NET Dependency Injection Containers (IOC)" post.
How to build an abstraction over DI framework?
If you want to configure dependency injection infrastructure without being dependent on a particular implementation, then you can build your own abstraction over DI implementation.
To achieve this, I prefer to define the abstraction by defining two interfaces needed to have their implementations in your chosen DI framewor and a base bootstrapper class that needs to be extended in the target application. At the following you can find sample codes when Unity is the chosen DI framework.
Resolver and Registrator interfaces
Resolver and Registrator implementations for Unity
Boostrapper base class
References
- Martin Fowler, 2004, http://martinfowler.com/articles/injection.html
- Nate Kohari, 2007, http://kohari.org/2007/08/15/defending-dependency-injection/#comment-950
- Google, http://code.google.com/p/google-guice/
- Wikipedia, Dependency Injection, http://en.wikipedia.org/wiki/Dependency_Injection
- MSDN, Bootstrapper, http://msdn.microsoft.com/en-us/library/ff921139(v=pandp.20).aspx
Comments