Wednesday, October 1, 2008

How To Renew Temporary Driving License

Automatic Dependency Injection with Unity Application Block

On this occasion I will comment on the Dependency Injection container using Microsoft Unity Application Block.

To begin this story, and especially for those who know nothing about this we can start by reading Martin Fowler's article on his website is a good introduction to pattern Inyection Dependency.

People Patterns and Practices for Microsoft, responsible for Enterprise Library, offers a DI container named Unity Application Block (name, true to form) this tool makes it easier for us when working with Object Builder by encapsulating its functions, if any of you have had to work with OB know what I mean. We can also configure our container through an XML configuration file to do it more clear and declarative (webconfig) in a few months ago InfoQ published an interview Chris Tavares who is the lead developer of Enterprise Library and Unity ( can view the note is very interesting too ).

Now either because Dependency Injection? Consider the classic example, if we have a Logger class, a container of DI would allow us to create a dependency ILogger interface, so that later in runtime can decide that specific logger to use (aLogger, MyLogger, customLogger, etc). While not a total descople and to keep the dependence on ILogger I am taking the maximum free themselves from dependence on the specific types, and that's what Unity pursued.

Let us look at Unity in action

The first thing to do is download the Microsoft Unity Application Block can get to it from the Downloads section of Microsoft Patterns & Practices here or from the version 1.1 . Once the installer (msi package), we are ready for first test with our DI container.

Then in your project (for this example I'll use a console application to display the results) add a reference to

Microsoft.Practices.Unity Microsoft.Practices.Unity.Configuration and


Now well, let's see how to configure your container from the App.config file to add to our project.



  
<? xml version ="1.0" encoding ="utf-8" ? >
< configuration >
< configSections >
< section name ="unity"
type ="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/>
</ configSections >
< unity >

< typeAliases >
...
</ typeAliases >

< containers >
< container name = "containerOne" >
\u0026lt; types >

\u0026lt;/ types >
\u0026lt;/ container> ;
\u0026lt;/ containers >

\u0026lt;/ unity >
\u0026lt;/ configuration >
Here we define a section customized configuration unity for the container and then defininos a container that is called in this case "containerOne." Note also that we have a node in definimeros typeAliasses alias to avoid having to use the full name of the classes and assemblies whenever we refer to them. In the types section there will our objects to be injected. Section typeAliasses Now we can place the following lifeTimeManagers




  
<!-- Lifetime manager types -->
< typeAlias alias ="singleton"
type ="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,
Microsoft.Practices.Unity"
/>
< typeAlias alias ="external"
type ="Microsoft.Practices.Unity.ExternallyControlledLifetimeManager,
Microsoft.Practices.Unity"
/>


And also we will put our nickname there are going to provide the reference then the node types.
Forget for a moment the configuration file and see some of the code example (this example code is based on an existing one in the blog of Matthew Podwysocki's ). Let
:




 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Configuration;
using Microsoft. Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

namespace UnityAppBlockEjemplo

{public interface ILogger
{
void log ( string message);}


public interface iProductivity

{string name {Get, set;}
double price {get, set;}}


public interface IServicioProducto
void {
GuardarProducto (iProductivity product)


} public class ConsoleLogger: ILogger

{public void log ( string message) {

Console.WriteLine (message);}



} public class Product: {

iProductivity public string Name {get; set;} public
double price {get, set;}

public override string ToString () {

return this . name + "($" + this . precio.ToString () + ")" ;

}} public

ServicioProducto class: {
ILogger
IServicioProducto mylog;
public
ServicioProducto (ILogger logger) {

mylog = logger;}


public void GuardarProducto (iProductivity product)

{string message = producto.ToString() + " - GUARDADO" ;
Mylog.log(mensaje);
}
}

class Program
{
static void Main( string [] args)
{
IUnityContainer myContainer = new UnityContainer();

// load container configuration from App.config
UnityConfigurationSection section =(UnityConfigurationSection) ConfigurationManager.GetSection( "unity" );
section.Containers[ "containerOne" ].Configure(myContainer);

// inyect a IProduct instance
IProductivity myContainer.Resolve \u0026lt;IProducto> myProduct = ();
myProduct.nombre = "tomatoes" ;
myProduct.precio = 4.59;

/ / injected IServicioProducto instance
IServicioProducto srvProducto = myContainer.Resolve \u0026lt;IServicioProducto> ();
srvProducto.GuardarProducto (myProduct)

/ / wait for user
Console.WriteLine ( "Press enter to exit" )
Console.ReadLine ();

}}}



And here we see how the file is complete typeAliasses node configuration with the alias defined for me.




  
<!-- User-defined type aliases -->
< typeAlias alias ="IProducto" type ="UnityAppBlockEjemplo.IProducto, UnityAppBlockEjemplo" />
\u0026lt; typeAlias \u200b\u200b alias = "Product" type = "UnityAppBlockEjemplo.Producto, UnityAppBlockEjemplo" />
\u0026lt; typeAlias \u200b\u200b alias = "ILogger" type = "UnityAppBlockEjemplo.ILogger, UnityAppBlockEjemplo" />
\u0026lt; typeAlias \u200b\u200b alias = "IServicioProducto" type = "UnityAppBlockEjemplo . IServicioProducto, UnityAppBlockEjemplo " />
\u0026lt; typeAlias \u200b\u200b alias = "ConsoleLogger" type = "UnityAppBlockEjemplo.ConsoleLogger, UnityAppBlockEjemplo" />
\u0026lt; typeAlias \u200b\u200b alias = "ServicioProducto" type = "UnityAppBlockEjemplo.ServicioProducto, UnityAppBlockEjemplo" />


Let

soon as I complete my configuration file specifying the node types of "mapping "Type in the following way:





 
\u0026lt; types >
\u0026lt; type type = "iProductivity" MAPT = "Product" />
\u0026lt; type type = "ILogger" MAPT = "ConsoleLogger" />
\u0026lt; type type = "IServicioProducto" MAPT = "ServicioProducto" /> ;
\u0026lt;/ types >


Well explain a little this happening here. As you will see the code is very simple and easy to follow, we have 3 interfaces ILogger, IServicioProducto iProductivity and then have 3 concrete classes that implement 3 interfaces are ConsoleLogger earlier, Product and ServicioProducto. Implementations are trivial. Let's see what happens in the main, first created a new Unity container instance doing, then by the container "containerOne" from the App.config file.
After doing this I am able to "ask" my container for me to desire iProductivity implementation, here is where the "magic" at no time did I

product = new Product iProductivity ();


Avoid new to indicate who will provide the product instance, and I do through my ID container. This gives me an interesting decoupling between classes as I could have if you want more implementations iProductivity that differ from each other and point at runtime type is that I receive at all times. The same with the logger, I can have XMLLogger ConsoleLogger or at runtime and change the type of logger since I'm "programming against interfaces and not against specific types" .

If we look closely at the code ServicioProducto class we see that the constructor is overloaded and get an object of type as a parameter ILogger, now when we ask the container object type in
IServicioProducto
IServicioProducto srvProducto = MyContainer. Resolve ();

can see how the Unity container is responsible for resolving for us the assignment of object in the constructor, in this case we say that dependency injection is of type Constructor Inyection with Unity Inyection Setter also can do (that's for another post.)

Final words

As you will realize this is just the "tip of the iceberg" of what we can do with the dependency injection, I have a worked example where I use the same principle to change at runtime the mechanism to persist the objects Product, selecting from a list of objects in memory and db4objects database.
What we see here gives us a powerful and practical tool for descoplada make it our architecture and achieve a much more flexible, while this tool allows me to ignore how tedious it is to work with the Object Builder.
One of the highlights of the dependency injection is that it is intimately linked to the AOP (Aspect Oriented Programming), if they know nothing about this can start here wiki. Unity does not yet provide a mechanism to intercept methods nor an AOP framework, maybe in the future, time will tell. Other DI containers that can be tested and used are Spring.NET Spring.NET and WindsorCastle.Con about this is a very complete and very flexible framework (Spring is a framework widely used in the Java environment) that I personally love it.

0 comments:

Post a Comment