On this occasion I will comment on the Dependency Injection container using Microsoft Unity Application Block.
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 >
<!-- 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" />
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 ();
}}}
<!-- 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" />
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 >
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.
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