No nos llames, nosotros lo haremos
Como luce la Inversión de control un sistema usado frameworks de desarrollo?

3 layer Example of NHibernate + Spring.Net + AOP
Hace un tiempo escribí este proyecto plantilla usando Spring.Net y NHibernateprincipalmente. Usé NHibernate para el acceso a datos obviamente y Spring.Net para aplicar IoC y Aop.
Esta es la clase CustomerService:
public class CustomerService : BaseService, ICustomerService
{
/// <summary>
/// This field is inyected by IoC through the property.
/// </summary>
private ICustomerDao customerDao;
public ICustomerDao CustomerDao {
get { return customerDao; }
set { customerDao = value; }
}
#region ICustomerService Members
public int CreateCustomer(string Name, string LastName) {
Customer customer = new Customer();
customer.FirstName = "Dario";
customer.LastName = "Quintana";
CustomerDao.Save(customer);
return customer.Id;
}
public void DeleteCustomer(int Id) {
Customer customer = CustomerDao.GetById(Id);
CustomerDao.Delete(customer);
}
#endregion
}
Como se puede apreciar las clases CreateCustomer ó DeleteCustomer no están envueltas en un codigo Transactional o de UnitOfWork, tampoco el método Save(customer) en la clase CustomerDao.
Entonces… donde está el soporte transaccional? Spring + AOP es la respuesta. Spring envuelve a los metodos del Servicio entre transacciones. Y la respuesta para esto son los proxies.
Cuando se realiza la instanciación de la clase CustomerService, un proxy es instanciado. Con el proxy de nuestra clase Spring.Net puede envolver los metodos configurados dentro de transacciones. Muy bueno no ?
Otra cosa que pueden apreciar en el ejemplo es el uso de uNhAddIns en el repositorio. Con esta librería podemos usar queries "detachadas" o separadas de un contexto de persistencia por medio de la clase DetachedQuery. Con DetachedQuery podemos hacer uso indistinto de Hql/SqlNativo en NamedQueries, y esto es una buena práctica que debemos tratar de adoptar.
Descargar el ejemplo
Mono.Sms y Windsor Container
Para ponerle un poco de sabor al Core de Mono.Sms, una de las cosas que me encargué de añadir es la capacidad solicitar los proveedores que estén disponibles para enviar mensajes por medio de un container de IoC. Para los que no sepan que es esto, pueden tener una introducción aquí con Spring.Net, o aquí utilizando Windsor.
Para dicha Inversion de Control (IoC) estoy usando Windsor Container.
Este caso todos los proveedores son inyectados, es decir, dejo que el container me entregue en mano, todas la implementaciones existentes de IProvider para la aplicación. Cada proveedor implementa la interfaz IProvider:
namespace Mono.Sms.Core.Provider { public interface IProvider { string Name { get; set; } string Domain { get; set; } bool UseSmtp { get; set; } string HostName { get; set; } string DataPost { get; } string Sign { get; } string Message { get; set; } CelNumber CelNumber { get; set; } int NumberOfCharacters { set; get; } string Description { get; set; } } }
y luego configuro los proveedores para que Windsor sepa sobre ellos y pueda crear los objetos:
<castle> <components> <component id="ProviderPersonalPost" service="Mono.Sms.Core.Provider.IProvider, Mono.Sms" type="Mono.Sms.Core.Provider.PersonalProvider, Mono.Sms" lyfestyle="singleton" > <parameters> <Name>Personal</Name> <Domain>@personal-net.com.ar</Domain> <UseSmtp>false</UseSmtp> <HostName>host25.200-43-139.telecom.net.ar</HostName> <Port>80</Port> <NumberOfCharacters>138</NumberOfCharacters> <Description>Este proveedor permite la entrega de mensajes a un celular Personal</Description> </parameters> </component> <component id="ProviderPersonalMail" service="Mono.Sms.Core.Provider.IProvider, Mono.Sms" type="Mono.Sms.Core.Provider.PersonalProvider, Mono.Sms" lyfestyle="singleton" > <parameters> <Name>Personal</Name> <Domain>@personal-net.com.ar</Domain> <UseSmtp>true</UseSmtp> <HostName>host25.200-43-139.telecom.net.ar</HostName> <Port>80</Port> <NumberOfCharacters>110</NumberOfCharacters> <Description>Este proveedor permite la entrega de mensajes a un celular Personal utilizando mails.</Description> </parameters> </component> </components> </castle>
En este caso hemos creado 2 implementaciones para enviar mensajes a una misma empresa, una forma es haciendo un post, y la otra utilzando mails. Hablando en el idioma de Windsor container, hemos creado aquí 2 Componentes (ProviderPersonalPost y ProviderPersonalMail), para un mismo Servicio (IProvider).
Luego para pedirle al container que nos entregue todas las implementaciones de los servicios IProvider, realizo esta siguiente iteración:
public IList<IProvider> GetAllProviders() { IHandler[] handles = container.Kernel.GetHandlers(typeof (IProvider)); IList<IProvider> providersImpl = new List<IProvider>(); foreach (IHandler hdlr in handles) { providersImpl.Add((IProvider)hdlr.Resolve(CreationContext.Empty)); } return providersImpl; }
Se puede ver que agrego a una lista providersImpl todos los proveedores y los retorno. Y con esto tengo en mano a todos los proveedores con los que puedo mandar mensajes.
Se preguntarán: “Es necesario todo esto para una simple aplicación de sms?”, la respuesta es “No”. Como se sabe, IoC es un principio de diseño, y no un requerimiento indispensable.
Opiniones ? Sientanse como en casa
Mono.Sms para enviar mensajes
Mono.Sms es una aplicación que se escribió para mandar mensajes de texto en Argentina a clientes de empresas como Personal, Cti, y Movistar. La ventaja es que lo podemos correr tanto en Linux y Windows. Aquí les mando un screenshot del preview:
Dentro de poco se podrá bajar el binario para usarlo, con los nombres de los coders de esta app.
AOP en el Enterprise Library?
Un nuevo Application Block nació: Policy Injection Application Block.
Al parecer, con este nuevo App Block podremos aplicar conceptos como el de SoC (Separation of concerns) en nuestra aplicación, tal como lo venían predicando de manera similar frameworks como Spring.Net.
Para ser claro, podriamos hacer que en un objeto de nuestra aplicación, al ejecutarse un método, realice una entrada al archivo de log, de forma transparente en el código cliente.
Esto se pone más interesante, en la interoperabilidad que podremos llegar a tener con otros App Blocks, como ser: Validation, Logging, Exception entre otros.
La idea básica es trabajar con una factoría de clases, para la instanciación de nuestros objetos. Dicha factoria inspeccionará la configuración, para ver si el objeto posee politicas que aplicar, si no las posee, se crea una instancia común y corriente, si las posee, se crea un proxy para que el framework pueda manejar al objeto de forma transparente al cliente.
Escenario donde podriamos aplicar:
En nuestra aplicación un objeto que posee un método Guardar(Cliente obj). Utilizando estos conceptos, podríamos hacer que cada vez que se llame a este método, es decir, que querramos guardar un cliente, por medio del Policy Injection App Block se realize la validación del objeto (utilizando el Validation App Block), y si no es una entidad válida, dicho método Guardar no se ejecute.
Para más lean estos posts:
Inyección de Dependencia con Spring.Net
Spring.Net es uno de los frameworks más conocidos para implementar Inyección de Dependencia (también conocido como Inversión de Control -IoC). Otros que nos permiten hacer este trabajo son: PicoContainer, ObjectBuilder, Windsor Container.
Basicamente, qué queremos lograr? Fácil, crear nuestros objetos, sin importar quién me provea la implementación.
En vez de hacer esto:
(1) Cliente obj_cliente = new Cliente();
Podemos hacer esto:
(2) ICliente obj_cliente = (ICliente) AppContext.Instance.GetObject("Cliente");
Expliquemos, en (1) le estamos diciendo a obj_cliente quién va a crearlo: new Cliente(); Es decir, le estamos diciendo quien le va a proveer de la implementación, y nunca vamos a poder cambiar esto, a menos que lo hagamos y volvamos a compilar. En (2) es distinto, estamos pidiendo una implementación, pero no sabemos quien nos la va a dar. Solo sabemos que quién nos proveea la construcción, va a implementar la interfaz ICliente. AppContext es un wrapper que hice para crear un singleton del contexto de toda la aplicación (está en el codigo fuente que se puede descargar más abajo).
El lugar donde le decimos qué clase se va a encargar de la implementación, es en el app.config (en una de las tantas lineas para configurar Spring.Net):
<object name=?Cliente? type=?Entities.Cliente, Entities? singleton=?false?/>
En esta línea de código Entities.Cliente es la Clase que nos proveerá la implementación, y Entities es el assembly (que TIENE que estar en la carpeta de salida, donde está el .exe). También podemos ver cuan fácil es implementar un singleton de esta manera, solamente escribiendo singleton=”true” (ú obviandolo, es el valor por defecto), entonces no tenemos que hacerlo programaticamente.
Para el ejemplo lo que hice es organizar los proyectos de esta forma:
Lo que hariamos normalmente es referenciar Entities desde todas las partes del proyecto, en vez de esto, lo haremos con Entities.Contracts que contienen las interfaces, de modo que siempre programaremos contra las interfaces, nunca contra la implementación. Los proyectos no poseen relación de conocimiento con Entities, en ningún momento se lo referencia.
El tip del día: Hay que programar contra las interfaces.
Descargar codigo fuente [Proyecto hecho con SharpDevelop]
Donde más podemos utilizarlo ? En la capa de acceso a datos, podríamos persistir los objetos con db4o, y en otra implementación lo podríamos hacer usando NHibernate! Y esto lo lograríamos creando una interfaz IBaseRepository que tenga metodos como Guardar, Eliminar, Buscar y luego crear las implementaciones para cada uno de los providers por ejemplo BaseRepositoryDb4o y BaseRepositoryNH.
Espero que sirva!