viernes, 25 de septiembre de 2009

Inyección de Dependencia con Spring.NET

Hola, para comenzar a usar Spring.NET en nuestras aplicaciones, el primer paso que se debe seguir para ello es comprender qué es la "inyección de dependencia" que es el corazón en el marco de trabajo que usa Spring.

Voy a usar un definición en forma de ejemplo que creo que aclara mejor el concepto:
Cualquier aplicación "normal" está compuesta por clases, y estas clases se componen de otras clases, es decir, colaboran entre sí para obtener un resultado.
Normalmente un objeto es el responsable de obtener las referencias de los objetos que lo componen o colaboran. Cuyo inconveniente es el acoplamiento entre ellas.
Con la inyección de dependencia son los objetos colaboradores los que se inyectan al objeto principal. Ventaja, acoplamiento débil.
El truco, está en que los objetos conocen sus colaboradores mediante interfaces, de este modo, podemos cambiar la implementación de los colaboradores sin que el objeto principal se entere.

Para poder entenderlo, que mejor que un ejemplo:

Este sería el código sin utilizar la ID:


public class Persona
{
private string _nombre;
private Trabajo _trabajo;

public string Nombre
{
get { return _nombre; }
set { _nombre = value; }
}

public ITrabajo Trabajo
{
get { return _trabajo; }
set { _trabajo = value; }
}

public Persona()
{ }

public Persona(string nombre)
{
this._nombre = nombre;
this._trabajo = new Trabajo();
}

public string trabajaEn()
{
return _trabajo.obtenerNombreTrabajo();
}
}


Como podeis ver la clase persona es la que se encarga de instanciar el objeto Trabajo. Esto convierte el código fuertemente acoplado.

Ahora mostraremos el código fuente utilizando la Inyección de Dependencia:

public class Persona
{
private string _nombre;
private ITrabajo _trabajo;

public string Nombre
{
get { return _nombre; }
set { _nombre = value; }
}

public ITrabajo Trabajo
{
get { return _trabajo; }
set { _trabajo = value; }
}

public Persona()
{ }

public Persona(string nombre)
{
this._nombre = nombre;
}

public string trabajaEn()
{
return _trabajo.obtenerNombreTrabajo();
}
}




public interface ITrabajo
{
string obtenerNombreTrabajo();
}




public class Ingeniero : ITrabajo
{
private string _nombre;

public string Nombre
{
get { return _nombre; }
set { _nombre = value; }
}

public Ingeniero()
{
this._nombre = "ingeniero";
}

#region Miembros de ITrabajo

public string obtenerNombreTrabajo()
{
return this._nombre;
}

#endregion
}



public class Carpintero : ITrabajo
{
private string _nombre;

public string Nombre
{
get { return _nombre; }
set { _nombre = value; }
}

public Carpintero()
{
this._nombre = "carpintero";
}

#region Miembros de ITrabajo

public string obtenerNombreTrabajo()
{
return this._nombre;
}

#endregion
}


"inem.xml"

<objects xmlns="http://www.springframework.net">

<object id="Carpintero" type="SpringNET_DI_Console_1.Class.Carpintero, SpringNET_DI_Console_1" />

<object id="Ingeniero" type="SpringNET_DI_Console_1.Class.Ingeniero, SpringNET_DI_Console_1" />

<object id="Ivan" type="SpringNET_DI_Console_1.Class.Persona, SpringNET_DI_Console_1" >
<property name="Nombre" value="Iván" />
<property name="Trabajo" ref="Ingeniero" />
</object>

</objects>


El fichero xml es el que contiene cómo deben montarse los objetos, es decir, la instanciación de las clases, con ello Spring se encarga de inyectarle los objetos colaboradores como son Carpintero o Ingeniero al objeto de tipo Persona "Ivan".

El truco está en que la clase Persona tiene la declaración de Trabajo como una interface ITrabajo, así podemos implementar de diferentes formas los trabajos sin que la clase Persona se de cuenta. Conseguimos un acoplamiento débil.

De esta forma a "Ivan" de tipo Persona le podremos asignar cualquier ITrabajo que nos apetecezca, sin que se queje, XD, siempre que estos "Trabajos" implementen la interfaz "ITrabajo". Se puede observar que esta técnica nos permite mucha flexibilidad para nuestros diseños de negocio.

Éste sería el código para ejecutar lo que hemos programado antes:

IApplicationContext ctx = new XmlApplicationContext("file://inem.xml");
Persona ivan = (Persona) ctx.GetObject("Ivan");

Console.Write(ivan.trabajaEn());


Espero que el ejemplo os haya servido de mucha ayuda, próximamente iré publicando nuevas entradas en que veamos a Spring.NET a pleno rendimiento.

Os dejo un ejemplo hecho con Visual Studio 2008 para descargar: descargar