Using object-oriented
design principles and features such as interface, inheritance, and
polymorphism, the IoC pattern enables better software design that facilitates
reuse, loose coupling, and easy testing of software components.
The Inversion of
Control (IoC), sometimes referred to as dependency injection (DI) (IoC vs DI),
is a straightforward application plumbing technique based on a common
programming practice. CBD frameworks that combine the declarative application
descriptions and the IoC technique are referred to as IoC frameworks.
IoC is all about
inverting the control. To explain this in layman's terms, suppose you drive a
car to your work place. This means you control the car. The IoC principle
suggests to invert the control, meaning that instead of driving the car
yourself, you hire a cab, where another person will drive the car. Thus, this
is called inversion of the control - from you to the cab driver. You don't have
to drive a car yourself and you can let the driver do the driving so that you
can focus on your main work.
1. Castle Windsor
2. Spring.NET
3. StructureMap
4. Unity
5. Autofac
6. Ninject
7. PicoContainer.NET
8. Puzzle.NET
9. LinFu
10. S2Container.NET
11. LightCore
12. TinyIoC
13. Hiro
Inversion
Of Controls Is About Separating Concerns
Without IoC: You have a laptop computer
and you accidentally break the screen. And darn, you find the same model laptop
screen is nowhere in the market. So you're stuck.
With IoC: You have a desktop computer
and you accidentally break the screen. You find you can just grab almost any
desktop monitor from the market, and it works well with your desktop.
Your desktop successfully implements IoC in
this case. It accepts a variety type of monitors, while the laptop does not, it
needs a specific screen to get fixed.
The Inversion of Control (IoC) and Dependency Injection (DI) patterns are
all about removing dependencies from your code.
For example, say
your application has a text editor component and you want to provide spell
checking. Your standard code would look something like this:
FOR EXAMPLE
public class TextEditor {
private SpellChecker checker;
public TextEditor() {
this.checker = new SpellChecker();
}
}
What we've done
here creates a dependency between the TextEditor and the SpellChecker. In an IoC scenario we would instead do something like this:
public class TextEditor {
private IocSpellChecker checker;
public
TextEditor(IocSpellChecker checker) {
this.checker = checker;
}
}
In the first code
example we are instantiating SpellChecker (this.checker = new SpellChecker();), which means the TextEditor class
directly depends on the SpellChecker class.
In the second code
example we are creating an abstraction by having the SpellChecker dependency class in TextEditor's constructor
signature (not initializing dependency in class). This allows us to call the
dependency then pass it to the TextEditor class like so:
SpellChecker sc = new SpellChecker; // dependency
TextEditor textEditor = new TextEditor(sc);
Now the client
creating the TextEditor class has control over which SpellChecker implementation to
use because we're injecting the dependency into the TextEditor signature.
Write down that
part of the presentation in an introduction to Inversion of Control, using
Dependency Injection and Service Locator along with some examples in .NET.
According to it Inversion of Control is a way to invert the flow of control in
comparison to procedural programming. What that means is that in procedural
programming a chunk of code that uses, or consumes, another chunk of code is in
control of the process. It knows exactly what piece of code, what method in
what class, it uses. And in doing so it is also quite likely that it knows
about some implementation details in the code it uses.
One example of such a scenario and of such a dependency is when a class,
illustrated as X below, uses another class Y.
The consumer, X, needs the
consumed class, Y, to accomplish something. That’s all good and natural, but
does X really need to know that it uses Y?
Isn’t it enough that X knows that
it uses something that has the behavior, the methods, properties etc, of Y
without knowing who actually implements the behavior?
By extracting an abstract
definition of the behavior used by X in Y, illustrated as I below, and letting
the consumer X use an instance of that instead of Y it can continue to do what
it does without having to know the specifics about Y.
In the illustration above Y
implements I and X uses an instance of I. While it’s quite possible that X
still uses Y what’s interesting is that X doesn’t know that. It just knows that
it uses something that implements I.
That could be Y, but it could also
be A, B or C given that they implement I. Of course this discussion is rather
abstract at the moment, but we’ll get to how to implement this in a second
using either Dependency Injection or Service Locator.
For now, let’s just assume that we
can and that we can change what implementation of I X uses at runtime. What
benefits can we get from that?
Benefits of Inversion of Control
X is not
dependent on Y anymore and it’s therefore less likely that we’ll have to
make changes to X when we make changes in Y as we’re less likely to write code
in X that relies on implementation details in Y.
X is now
much more flexible as we can change which implementation of I it uses without
changing anything in X.
Perhaps Y is a
component for sending e-mails and we want X, who used to send e-mails, to start
sending tweets instead using Z who also implements I.
Isolate our code when
creating unit tests. Suppose, as before, that X used Y to send messages which Y
did in the form of e-mails using an SMTP-server. When creating unit test, which
should only test a single unit of code, we want to be able to test the logic in
X without having to care about the component that sends messages, and we most
definitely don’t want our tests to fail because Y doesn’t have access to an
SMTP server.
A Sample Scenario
We have a class
named OrderService which is used for
processing orders.
It has a method named AcceptOrder
which receives an Order object, validates that it is valid according to the
business rules (it may for instance check that the order’s shipping address is
a valid address and that there are enough items in stock) and then, given that
the order is valid, saves it to a database using another class named OrderDatabase.
The code for OrderService looks
like this:
public class OrderService
{
public void AcceptOrder(Order order)
{
//Domain logic such as validation
new OrderDatabase().SaveOrder(order);
}
}
In the
real world SaveOrder could be static, making line seven in the example look
like this:
OrderDatabase.SaveOrder(order);
A singleton
implementation of OrderDatabase making line seven look like this:
OrderDatabase.Instance.SaveOrder(order);
Relying on it is
inflexible and bad for testability.
For the sake of this example let’s assume it’s SaveOrder method looks like
this:
public void SaveOrder(Order order)
{
throw new ApplicationException("I need
a database to work");
}
To fix this we
apply Inversion of Control by creating an abstract definition of the behavior
in OrderDatabase that OrderService needs in the form of the interface IOrderSaver and making
AcceptOrder use an instance of
IOrderSaver instead of an instance
of OrderDatabase.
OrderService no longer knows about the
OrderDatabase class. It just uses an instance of the IOrderSaver interface of
which OrderDatabase is one of possibly many implementation.
In fact we could easily change it so that
OrderService instead uses a class
that saves orders to XML files
instead, without changing a single line
of code in OrderService.
Or to a class that still saves to a database but that has
been extended with logging.
Or to a composite that saves both to a database and to an XML
file. Or to…
There would be little point in using the IOrderSaver
interface if OrderService still had to know how to instantiate a concrete
implementation of it, so we need a way for OrderService to get an instance of
IOrderSaver at runtime without knowing about any concrete implementations.
There are a couple of ways to do that. Let’s begin by looking
at Dependency Injection.
Dependency Injection
Using Dependency Injection we inject an instance of
IOrderSaver into OrderService when we use it.
This could either be done using constructor injection, where we supply the instance to OrderService’s constructor, or property injection where we supply it to OrderService after it has been instantiated
by setting a property on it.
In the diagram below I’ve tried to illustrate constructor
injection.
Notice how OrderService has a constructor which requires an
instance of IOrderSaver as a parameter.
In code this could be implemented like this:
public class OrderService
{
private IOrderSaver orderSaver;
public OrderService(IOrderSaver orderSaver)
{
this.orderSaver
= orderSaver;
}
public void AcceptOrder(Order order)
{
//Domain logic
such as validation
orderSaver.SaveOrder(order);
}
}
As you can see in the example code above OrderService’s
constructor requires an instance of IOrderSaver which it stores in a field.
When invoked the AcceptOrder method uses this injected instance to save
the order.
Should we want to be able to instantiate OrderService without
supplying an IOrderSaver there is of course nothing stopping us from creating
another constructor which sets the orderSaver field to a default
implementation.
public OrderService()
{
this.orderSaver = new
OrderDatabase();
}
While this means that OrderService still knows about which implementation of IOrderSaver it uses
when instantiated with this constructor we are still able to change what
implementation it uses using the other constructor, for instance when we are
creating unit tests.
Service Locator
While I think Dependency Injection is superior in just about
any situation there is also another way
to implement Inversion of Control, using a Service Locator.
In the diagram above OrderService doesn’t
know about OrderDatabase but it does know about an instance of the concrete
class ServiceLocator which in turn knows about OrderDatabase.
When AcceptOrder is invoked it will ask ServiceLocator for an
instance of IOrderSaver which will supply one based on how we have configured
it.
Using this approach OrderService could be implemented like
this:
public class OrderService
{
public void AcceptOrder(Order order)
{
//Domain logic
such as validation
OrderSaverFactory.GetOrderSaver().SaveOrder(order);
}
}
A simple implementation of ServiceLocator would be to have it
supply an instance of a default
implementation of IOrderSaver unless we specifically tell it to supply
another instance, like this:
public class ServiceLocator
{
public static IOrderSaver OrderSaver { get; set; }
public static IOrderSaver GetOrderSaver()
{
if (OrderSaver ==
null)
OrderSaver =
new OrderDatabase();
return OrderSaver;
}
}
I find the Service Locator approach to be much more messy
than Dependency Injection and it makes unit tests harder to set up, but there
might be a few situations where Dependency Injection may be impractical. Then
it’s good to still be able to apply Inversion of Control by using Service
Locator.