Tuesday, August 14, 2012

Dependency Injection with Microsoft Unity Application Block


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
  1. Constructor Injection
  2. Setter Injection
  3. 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 = newCreditCardValidator(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
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 = newCreditCardValidator();//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>
First you need to register interface with concrete object,
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>
REFERENCES

No comments:

Post a Comment