Dependency Injection (DI) vs. Inversion of Control
(IOC)
The main goal of Inversion of
control and Dependency Injection is to remove dependencies of an application.
This makes the system more decoupled and maintainable.
First let’s try to understand IOC
(Inversion of control). If you go back to old computer programming days,
program flow used to run in its own control. For instance let’s consider a
simple chat application flow as shown in the below flow diagram.
- End user sends chat message.
- Application waits for the message from the other end.
- If no message is found it goes to Step 2 or else moves to Step 4.
- Displays the message.
- User continues with his work ahead.
Now if you analyze the program flow
closely, it’s sequential. The program is in control of himself. Inversion of
control means the program delegates control to someone else who will drive the
flow. For instance if we make the chat application event based then the flow of
the program will go something as below:-
- End user sends chat message.
- User continues with his work ahead.
- Application listens to events. If a message arrives event is activated and message is received and displayed.
If you see the program flow it’s not
sequential, its event based. So now the control is inverted. So rather than the
internal program controlling the flow, events drive the program flow. Event
flow approach is more flexible as their no direct invocation which leads to
more flexibility.
A word of caution here, do not
conclude that IOC are implemented by only events. You can delegate the control
flow by callback delegates, observer pattern, events, DI (Dependency injection)
and lot of other ways.
IOC (Inversion of control) is a
general parent term while DI (Dependency injection) is a subset of IOC. IOC is
a concept where the flow of application is inverted. So for example rather than
the caller calling the method.
Collapse | Copy Code
SomeObject.Call();
Will get replaced with an event
based approach as shown below.
Collapse | Copy Code
SomeObject.WhenEvent += Call();
In the above code the caller is
exposing an event and when that event occurs he is taking action. It’s based on
the Hollywood principle “Don’t call us we will call you”. In Hollywood when
artists used to give auditions the judges would say them “Don’t call us we will
call you”.
The above approach makes code more
flexible as the caller is not aware of the object methods and the object is not
aware of caller program flow.
DI provides objects that an object
needs. So rather than the dependencies construct themselves they are injected
by some external means. For instance let’s say we have the following below class
“Customer” who uses a “Logger” class to log errors. So rather than creating the
“Logger” from within the class, you can inject the same via a constructor as
shown in the below code snippet.
The biggest benefit achieved by the
above approach is “Decoupling”. You can now invoke the customer object and pass
any kind of “Logger” object as shown in the below code.
Collapse | Copy Code
Customer obj = new Customer(new
EmailLogger());
Customer obj1 = new Customer(new
EventViewerLogger());
So summarizing the
differences.
Inversion of control :- It’s a generic term and implemented in several ways
(events, delegates etc).
Dependency injection :- DI is a subtype of IOC and is implemented by constructor
injection, setter injection or method injection.
Via this blog i would like to inform
all my friends i have started a series called as Learn c# and .NET
in 60 days in youtube. So if you have some
fresher friends who want to learn c# please talk about
this initiative. http://www.youtube.com/watch?v=yh2SrzCkNQA
Feel free to visit my site for c#
design pattern interview questions with answers
Below is a nice video which
demonstrates IOC ( Inversion of control) and how its is different from DI (
Dependency injection)
Implementation of Dependency Injection Pattern in C#
Dependency Injection (DI) is a software design pattern that
allow us to develop loosely coupled code. DI is a great way to reduce tight
coupling between software components. DI also enables us to better manage
future changes and other complexity in our software. The purpose of DI is to
make code maintainable.
The Dependency Injection pattern uses a builder object to initialize objects
and provide the required dependencies to the object means it allows you to
"inject" a dependency from outside the class. For example, Suppose your
Client
class needs to use a Service
class component, then the best you can do is to make your Client
class aware of an IService
interface rather than a Service
class. In this way, you can
change the implementation of the Service
class at any time (and for how many times you want) without breaking the host
code.
Constructor Injection
1. This
is the most common DI.
2. Dependency
Injection is done by supplying the DEPENDENCY through the class’s constructor
when instantiating that class.
3. Injected
component can be used anywhere within the class.
4. Should
be used when the injected dependency is required for the class to function.
5. It
addresses the most common scenario where a class requires one or more
dependencies.
1. public interface IService
2. {
3. void Serve();
4. }
5.
6. public class Service : IService
7. {
8. public void Serve()
9. {
10. Console.WriteLine("Service Called");
11. //To Do: Some Stuff
12. }
13.}
14.
15.public class Client
16.{
17. private IService _service;
18.
19. public Client(IService service)
20. {
21. this._service = service;
22. }
23.
24. public void Start()
25. {
26. Console.WriteLine("Service Started");
27. this._service.Serve();
28. //To Do: Some Stuff
29. }
30.}
31.class Program
32.{
33. static void Main(string[] args)
34. {
35.Client client = new Client(new Service());
36. client.Start();
37.
38. Console.ReadKey();
39. }
40.}The Injection happens in the constructor, by passing the Service that implements the IService-Interface. The dependencies are assembled by a "Builder" and Builder responsibilities are as follows:
1. knowing
the types of each IService
2. according
to the request, feed the abstract IService to the Client
Property injection
1. Also
called Setter injection.
2. Used
when a class has optional dependencies, or where the implementations may need
to be swapped. Different logger implementations could be used this way.
3. May
require checking for a provided implementation throughout the class(need to
check for null before using it).
4. Does
not require adding or modifying constructors.
1. public interface IService
2. {
3. void Serve();
4. }
5.
6. public class Service : IService
7. {
8. public void Serve()
9. {
10. Console.WriteLine("Service Called");
11. //To Do: Some Stuff
12. }
13.}
14.
15.public class Client
16.{
17. private IService _service;
18.
19. public IService Service
20. {
21. set
22. {
23. this._service = value;
24. }
25. }
26.
27. public void Start()
28. {
29. Console.WriteLine("Service Started");
30. this._service.Serve();
31. //To Do: Some Stuff
32. }
33.}
34.class Program
35.{
36. static void Main(string[] args)
37. {
38. Client client = new Client();
39. client.Service = new Service();
40. client.Start();
41.
42. Console.ReadKey();
43. }
44.}
Method injection
1. Inject
the dependency into a single method, for use by that method.
2. Could
be useful where the whole class does not need the dependency, just the one
method.
3. Generally
uncommon, usually used for edge cases.
1. public interface IService
2. {
3. void Serve();
4. }
5.
6. public class Service : IService
7. {
8. public void Serve()
9. {
10. Console.WriteLine("Service Called");
11. //To Do: Some Stuff
12. }
13.}
14.
15.public class Client
16.{
17. private IService _service;
18.
19. public void Start(IService service)
20. {
21. this._service = service;
22. Console.WriteLine("Service Started");
23. this._service.Serve();
24. //To Do: Some Stuff
25. }
26.}
27.class Program
28.{
29. static void Main(string[] args)
30. {
31. Client client = new Client();
32. client.Start(new Service());
33.
34. Console.ReadKey();
35. }
36.}
points about DI
1. Reduces
class coupling
2. Increases
code reusing
3. Improves
code maintainability
4. Improves
application testing
No comments:
Post a Comment