What is Dependency Injection?
DI is also known as Inversion of Control (IOC). It is a design pattern that remove tight coupling between dependent components. It facilitates the design and implementation of loosely coupled, reusable, and testable objects in your software designs by removing dependencies that often inhibit reuse. Instead of compile time dependencies it offers runtime loading and initialization of components, which makes solutions load on demand.
There are following advantages and disadvantages of Dependency Injection
Primary advantages:
- Loose coupling
- Centralized configuration
- Easily testable
Disadvantages:
- Debugging components while development because finding concrete objects may be tedious task.It make code harder to understand and more difficult to modify.
- Wiring instances together can become a nightmare if there are too many instances and many dependencies that need to be addressed.
Different types of Dependency Injection
- Constructor Injection
- Setter Injection
- Interface-based injection
Constructor Injection
In this injection type, dependencies can be injected through parameters in constructor of class. It is widely used in Unit Testing with Mocking objects.
Here is example (Please note: this example is not real solution of credit card validation, it is just for example purpose).
01.
public
class
CreditCardValidator
02.
{
03.
private
ICreditCard _card;
04.
05.
public
CreditCardValidator(ICreditCard card)
06.
{
07.
_card = card;
08.
}
09.
10.
public
bool
Validate()
11.
{
12.
return
_card.Validate();
13.
}
14.
}
In below code I am injecting instance of VisaCard and MasterCard classes from outside to validate card no.
01.
public
interface
ICreditCard
02.
{
03.
string
CardNo {
set
; }
04.
bool
Validate();
05.
}
06.
public
class
MasterCard : ICreditCard
07.
{
08.
private
string
_cardno;
09.
public
bool
Validate()
10.
{
11.
return
true
;
12.
}
13.
14.
public
string
CardNo
15.
{
16.
set
{ _cardno = value; }
17.
}
18.
19.
}
20.
public
class
VISA : ICreditCard
21.
{
22.
private
string
_cardno;
23.
24.
public
bool
Validate()
25.
{
26.
return
true
;
27.
}
28.
29.
public
string
CardNo
30.
{
31.
set
{ _cardno = value; }
32.
}
33.
}
34.
35.
static
void
Main(
string
[] args)
36.
{
37.
ICreditCard visaCard =
new
VISA();
38.
visaCard.CardNo =
"123123123"
;
39.
ICreditCard mastercard =
new
MasterCard();
40.
visaCard.CardNo =
"456456456"
;
41.
42.
Console.WriteLine(
"Validate Card"
);
43.
CreditCardValidator validator =
new
CreditCardValidator(visaCard);
44.
Console.WriteLine(
"Validating Visa Card Result: {0}"
, validator.Validate());
45.
validator =
new
CreditCardValidator(mastercard);
//again creating instance
46.
Console.WriteLine(
"Validating Master Card Result: {0}"
, validator.Validate());
47.
48.
Console.ReadLine();
49.
}
50.
51.
}
Output
Validate Card
Validating Visa Card Result: True
Validating Master Card Result: True
Validating Visa Card Result: True
Validating Master Card Result: True
Setter Injection
Setter injection uses properties to inject the dependencies, which lets you create and use resources as late as possible. It's more flexible than constructor injection because you can use it to change the dependency of one object on another without having to create a new instance of the class or making any changes to its constructor.Here's an example which will inject creditcard instance through properties in that case we don’t need to create instance of CreditCardValidator again.
01.
public
class
CreditCardValidator
02.
{
03.
private
ICreditCard _card;
04.
05.
public
ICreditCard Card
06.
{
07.
get
{
return
_card; }
08.
set
{ _card = value; }
09.
}
10.
11.
public
bool
Validate()
12.
{
13.
return
_card.Validate();
14.
}
15.
}
16.
static
void
Main(
string
[] args)
17.
{
18.
ICreditCard visaCard =
new
VISA();
19.
visaCard.CardNo =
"123123123"
;
20.
ICreditCard mastercard =
new
MasterCard();
21.
visaCard.CardNo =
"456456456"
;
22.
23.
Console.WriteLine(
"Validate Card"
);
24.
CreditCardValidator validator =
new
CreditCardValidator();
//creating instance one time only
25.
validator.Card = visaCard;
//setter injection
26.
Console.WriteLine(
"Validating Visa Card Result: {0}"
, validator.Validate());
27.
validator.Card = mastercard;
//setter injection
28.
Console.WriteLine(
"Validating Master Card Result: {0}"
, validator.Validate());
29.
30.
Console.ReadLine();
31.
return
;
32.
}
Interface Injection
Interface injection, by using a common interface that other classes need to implement to inject dependencies.
The following code shows an example in which the classes use the ICreditCard interface as a base contract to inject an instance of any of the credit card classes (VISA or MasterCard) into the CreditCardValidator class. Both the credit card classes VISA and MasterCard implement the ICreditCard interface:
01.
public
interface
ICreditCard
02.
{
03.
string
CardNo {
set
; }
04.
bool
Validate();
05.
}
06.
07.
public
class
MasterCard : ICreditCard
08.
{
09.
private
string
_cardno;
10.
public
bool
Validate()
11.
{
12.
return
true
;
13.
}
14.
15.
public
string
CardNo
16.
{
17.
set
{ _cardno = value; }
18.
}
19.
20.
}
21.
public
class
VISA : ICreditCard
22.
{
23.
private
string
_cardno;
24.
25.
public
bool
Validate()
26.
{
27.
return
true
;
28.
}
29.
30.
public
string
CardNo
31.
{
32.
set
{ _cardno = value; }
33.
}
34.
}
Dependency Injection with Unity Application Block
The Unity Application Block (Unity) is a lightweight extensible dependency injection container with support for constructor, property, and method call injection.
Unity is a general‐purpose container for use in any type of .NET Framework‐based application. It provides all of the features commonly found in dependency injection mechanisms, including methods to register type mappings and object instances, resolve objects, manage object lifetimes, and inject dependent objects into the parameters of constructors and methods and as the value of properties of objects it resolves.
Why you should implement Unity ?
- You wish to build your application according to sound object oriented principles (following the
five principles of class design, or SOLID), but doing so would result in large amounts of
difficult‐to‐maintain code to connect objects together. - Your objects and classes may have dependencies on other objects or classes.
- Your dependencies are complex or require abstraction.
- You want to take advantage of constructor, method, or property call injection features.
- You want to manage the lifetime of object instances.
- You want to be able to configure and change dependencies at run time.
- You want to intercept calls to methods or properties to generate a policy chain or pipeline containing handlers that implement crosscutting tasks.
- You want to be able to cache or persist the dependencies across post backs in a Web application.
Constructor Injection with Unity
01.
using
System;
02.
using
System.Collections.Generic;
03.
using
System.Linq;
04.
using
System.Text;
05.
using
Microsoft.Practices.Unity;
06.
07.
namespace
ParallelLibrarySamples
08.
{
09.
class
Program
10.
{
11.
12.
static
void
Main(
string
[] args)
13.
{
14.
15.
IUnityContainer uContainer =
new
UnityContainer();
16.
uContainer.RegisterType<icreditcard ,=
""
visa=
""
>();
17.
//it will automatically fires constructor of CreditCardValidator class
18.
CreditCardValidator myInstance = uContainer.Resolve<creditcardvalidator>();
19.
}
20.
}
21.
22.
public
class
CreditCardValidator
23.
{
24.
public
CreditCardValidator(ICreditCard card)
25.
{
26.
//card is VISA type
27.
card.Validate();
28.
}
29.
}
30.
}</creditcardvalidator></icreditcard>
1.
uContainer.RegisterType<icreditcard ,=
""
visa=
""
>();</icreditcard>
when you call resolve method of instance IUnityContainer, it will call constructor and find concrete object from IUnityContainer.
Setter Injection with Unity
For property injection you just need to put [Dependency] attributes on property, Unity framework will automatically create concrete object. The following code demonstrates property injection.
01.
static
void
Main(
string
[] args)
02.
{
03.
04.
IUnityContainer uContainer =
new
UnityContainer();
05.
uContainer.RegisterType<icreditcard ,=
""
visa=
""
>();
06.
07.
// CreditCardValidator myInstance = uContainer.Resolve<creditcardvalidator>();
08.
CreditCardValidator myinstance =
new
CreditCardValidator();
09.
myinstance.Validate();
10.
}
11.
public
class
CreditCardValidator
12.
{
13.
14.
private
ICreditCard _card;
15.
16.
[Dependency]
17.
public
ICreditCard Card
18.
{
19.
get
{
return
_card; }
20.
set
{ _card = value; }
21.
}
22.
23.
public
bool
Validate()
24.
{
25.
return
_card.Validate();
26.
}
27.
}</creditcardvalidator></icreditcard>
No comments:
Post a Comment