12.30.2009

Felices Fiesta !!!

Ahora que termina el año, quiero agredecer a todos los que se han tomado la molestia de leer mi blog, de hacer comentarios, sugerencias y críticas. Espero que lo escrito aquí les haya servido en sus actividades. Espero seguir el otro año escribiendo acerca de los temas más variados que se me ocurran, o como ocurrió este año, que ustedes sugieran. Si tienes interés en algún tema en específico, no dudes en escribirme a diego.rojas [at] gmail.com

Les dejó una postal del MSDN y que pasen un excelente año nuevo!!!

Technorati Tags:

Graficando en WPF Utilizando el WPF Toolkit

En muchos casos cuando se están desarrollando proyectos sobre todo a jefaturas o gerencias, se pide visualización de datos a través de gráficos ya sea en reportes o en pantalla. Normalmente para estos casos ya uno como desarrollador/consultor tiene una suite de controles para graficar que conoce y recomienda, sin embargo; no siempre la empresa que contrata o para la cual uno trabaja tiene presupuesto para invertir en controles – sin embargo para charts web les recomiendo la suite de componentArt – y entonces empieza la búsqueda de controles para graficar gratuitos o más accesibles. Esto por lo general es un verdadero dolor de cabeza porque aunque existen, no todos tienen todo lo que se necesita y por lo general el que pide estos gráficos tiene un gusto y necesidad muy refinado respecto a los datos que desea visualizar. 

Revisando el WPFToolkit de Junio del 2009, me encontré que este contiene – aunque en preview – la facilidad de realizar gráficas en WPF. En este post voy a explicar de forma breve como realizar un gráfico simple utilizando el toolkit y la librería para graficar.

Librerías a Incluir

Cuando se instala el WPF Toolkit, se agrega una cejilla en el toolbox de Visual Studio el cual contiene los controles existentes en el toolkit para graficar.

image

No solo podemos hacerlo de esta forma, si no que también podemos agregar una referencia al dll que contiene los controles de graficación System.Windows.Controls.DataVisualization.Toolkit.dll agregando el namespace en WPF para acceder a estos controles.

image

xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"



En primera instancia vamos a agregar un control de tipo Chart desde el toolbox, el cual es el contenedor de las series que vamos a graficar. El siguiente paso es agregar las series que deseamos ver en el gráfico, vamos a tener una serie por cada colección de datos que queremos graficar.



<chartingToolkit:Chart Margin="0,0,0,0" Name="chartBugs" Background="Silver" BorderBrush="Black" BorderThickness="3" Title="Bugs por Mes" LegendTitle="Bugs del mes" >
<
chartingToolkit:LineSeries Name="BugsReported" Title="Bugs Reported" DependentValuePath="Cantidad" IndependentValuePath="Fecha" AnimationSequence="FirstToLast">
</
chartingToolkit:LineSeries
>
<
chartingToolkit:LineSeries Name="BugsFixed" Title="Bugs Fixed" DependentValuePath="Cantidad" IndependentValuePath="Fecha" AnimationSequence="FirstToLast">
</
chartingToolkit:LineSeries
>
</
chartingToolkit:Chart>



En nuestro caso vamos a graficar las pulgas encontradas en la aplicación en un periodo determinado de tiempo, y las pulgas resueltas. Como podemos ver en el código anterior, la propiedad Title me permite identificar cada una de las series en la gráfica. Existen otras dos propiedades muy importantes que son las que me van a permitir hacer databining con el DataSource que vamos a asignar a cada una de las series, el DependentValuePath es el eje Y y el IndepdentValuePath es el eje X. En modo de diseño nuestra pantalla debe lucir así:



image



Ahora solo nos falta agregarle datos a las series para graficarlas. Estas series se pueden “ligar” al gráfico vía XAML o vía código .NET. En este ejemplo, vamos a utilizar C# para llevar a cabo esta tarea. El código que vamos a utilizar va a obtener la lista de pulgas – resueltas y agregadas – desde una lista genérica del tipo de una clase hecha específicamente para almacenar estas pulgas, esta contiene con dos propiedades una para la fecha y otra para la cantidad de pulgas agregadas. El código de esta clase es el siguiente:



public class BugsReported
{
public DateTime Fecha { get; set; }
public int Cantidad { get; set; }


public BugsReported(DateTime fecha, int cantidad)
{
Fecha = fecha;
Cantidad = cantidad;
}
}



Seguidamente procedemos a llenar las listas con datos aleatorios. Nótese que para agregar la fecha a cada llamado al constructor, utilizo DateTime.Now.AddDays(-X ), lo cual restará días al día actual. Los métodos que llenan ambas listas son los siguientes – se podría hacer uno solo, pero como el objetivo es el graficar entonces así más clarito:



private List<BugsReported> LoadBugReported()
{
BugsReported.Title = "Bugs Reported";
List<BugsReported> reportedBugs = new List<BugsReported>();
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-20), 3));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-19), 8));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-18), 7));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-15), 22));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-12), 9));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-8), 1));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-7), 12));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-6), 2));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-1), 8));

return reportedBugs;

}

private List<BugsReported> LoadBugFixed()
{

List<BugsReported> reportedBugs = new List<BugsReported>();
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-20), 1));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-19), 9));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-18), 4));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-15), 23));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-12), 8));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-8), 0));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-7), 1));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-6), 10));
reportedBugs.Add(new BugsReported(DateTime.Now.AddDays(-1), 7));

return reportedBugs;
}



Por último procedemos a ligar las listas con las series del gráfico. Para hacer esto, creamos una variable del tipo LineSeries – que se encuentra en el namespace 




System.Windows.Controls.DataVisualization.Charting;




- y le asignamos la serie que queremos llenar con datos del chart. Como podemos ver en el código el chart tiene una colección de series y su índice corresponde al orden en que las agregamos al chart. Por último, agregamos el datasource a la propiedad ItemsSource de la serie y listo, estamos graficando.



private void Window_Loaded(object sender, RoutedEventArgs e)
{
LineSeries lineSerieBugsReported = chartBugs.Series[0] as LineSeries;
if (lineSerieBugsReported != null)
{
lineSerieBugsReported.ItemsSource = LoadBugReported();
}

LineSeries lineSeriedBugsFixed = chartBugs.Series[1] as LineSeries;
if (lineSeriedBugsFixed != null)
{
lineSeriedBugsFixed.ItemsSource = LoadBugFixed();
}
}





El resultado al ejecutar el código anterior se puede ver en la siguiente figura:



image




Technorati Tags: ,

12.13.2009

¿Que Código pongo en mi Capa de UI ?

Esta es una pregunta constante que recibo vía blog, o cuando estoy trabajando en el diseño de alguna arquitectura en algún cliente. Normalmente, los desarrolladores comprenden bien de que se trata este asunto de las arquitecturas n-layer, comprenden que poner en la capa de acceso a datos, y tienen una idea general de lo que debe llevar la lógica de negocios. Pero cuando se habla de la capa de presentación hay serias dudas.  Estas dudas se dan principalmente porque estamos acostumbrados a escribir código en las pantallas de nuestras aplicaciones sin cuestionarnos si ese código debería ir en las pantallas – web, mobile, desktop – o no.

Para poder contestar esta pregunta, primero tenemos que entender que código debemos poner en las demás capas. De manera resumida, podemos decir que en la capa de acceso a datos vamos a escribir todo el código necesario para poder acceder nuestro repositorio de datos. Escribimos en esta capa las funciones para consultar, borrar, actualizar o ingresar datos, el código para conectarse a la base de datos y todo los relacionado con la interacción con los repositorios a los que accede nuestra aplicación. En la capa de lógica de negocios escribimos el código relacionado con el proceso que vamos a automatizar. Los objetos de negocio que tengan atributos ( cuando no dividimos el estado del objeto del el comportamiento ) tienen reglas de negocio en sus propiedades e incluso validaciones de asignación o retorno del dato en la propiedad. Nunca se debe acceder el estado del objeto directamente accediendo al atributo, siempre se deben utilizar métodos o propiedades. El siguiente diagrama nos muestra la composición de una instancia de un objeto de negocio y como se debe cambiar el estado del objeto.

image

Si se tiene capa de servicios, en esta capa no debe de tener código de lógica de negocios solamente invocación a componentes de negocio, esto principalmente porque si hay algún cambio a nivel del negocio, todas las interfaces que consumen esa lógica de negocios van a ver reflejado el cambio, sin importar si la consumen via servicio o directamente al componente.

Después de repasar que código poner en cada capa, nos queda solamente indicar que código realmente debemos tener en el UI:

  • Excepciones: Se deben de atrapar los errores que se presenten a nivel de interfaz gráfica y presentar al usuario un error que sea comprensible y que no asuste al usuario
  • Validaciónes: En la capa de UI deben de existir validaciones respecto a la interacción del usuario con la aplicación.
  • Databinding: Se agrega el código necesario para permitir el databinding entre los datos que despliegan controles del UI y que retornan las capas subyacentes.
  • Invocación a la capa de servicios o a la lógica de negocios: Deben de agregarse el código necesario para poder invocar la lógica de negocios de los componentes que estamos utilizando, ya sea a través de la capa de servicios o a través de la lógica de negocios directamente.

Y ahora se preguntarán: ¿En qué me beneficia esto? Pues esto nos va a permitir tener una separación real de capas, con lo que podemos cambiar de tipo de UI sin necesidad de modificar la aplicación, ya que la misma lógica de negocios se va a consumir sin importar el tipo de aplicación que queremos implementar. Si vemos con detenimiento el tipo de código que tenemos que poner en el UI, nos vamos a dar cuenta que por lo general es en estas secciones en donde existen variaciones entre los diversos tipos de UI, por ejemplo, el manejo de eventos para validar e invocar funcionalidad entre una aplicación desktop, una aplicación web, una aplicación mobile y una aplicación RIA.

Technorati Tags: ,

11.21.2009

WCF en una Arquitectura n-layer

Cuando desarrollamos aplicaciones n-layer y utilizamos diferentes tecnologías del framework, nos empezamos a cuestionar: ¿ y donde va esto? ¿qué rol juega esto en toda nuestra arquitectura? Esto es lo que normalmente sucede cuando empezamos a crear servicios – nótese que digo servicios no solamente servicios web – para exponer funcionalidad del negocio. La pregunta entonces es ¿Donde ponemos nuestros servicios? Es por esta razón que decidí escribir un post acerca de donde se deben ubicar los servicios en una arquitectura n-layer.

Esquema n-layer

En un esquema n-layer, debemos crear una capa de servicios – una librería -  la cual se ubicará sobre la capa de lógica de negocios. Esto nos va a permitir que los diversos usuarios se conecten siempre a la lógica de negocios ya sea con referencias directas a estas librerías o ingresando a través de la capa de servicios.

En el siguiente diagrama podemos ver esta distribución.

image En primera instancia este esquema nos permite darle mantenimiento a la aplicación de forma sencilla, ya que todos los cambios que le apliquemos a la lógica del negocio, se van a ver reflejados. Seguidamente nos permite activar workflows de negocio – que deberían ser parte de la lógica de negocios – ya sea directamente o a través de la capa de servicios.

Desde el punto de vista físico, acceder los componentes vía capa de servicios nos va a permitir tener un repositorio de componentes, desde donde podemos reutilizar nuestra lógica de negocios. Un escenario idea sería utilizar varios endpoints para cada servicio, permitiendo esto que si los servicios son consumidos dentro de la organización la comunicación se haga vía TCP, y si son consumidores externos que la comunicación se haga vía HTTP o HTTPS. Esto se puede lograr utilizando WCF y IIS 7.0 o superior + WAS.

Por último y no menos importante, usar la capa de servicios nos permitir programar usando contratos. Esto quiere decir que puedo cambiar la forma en que mi lógica de negocios este programada sin necesidad de solicitarle a los consumidores del servicio que realicen cambio alguno en sus sistemas – claro siempre y cuando no afecte el contrato ( la interface ).

Technorati Tags: ,,

11.18.2009

Costa Rica SOA & Cloud Computing User Group: 1era Presentación

El día de ayer lanzamos el grupo de usuarios en Costa Rica de SOA y Cloud Computing. Esta es la presentación que realizamos ayer. Más información en el blog de Yuri Porras.

CR SOA & Cloud Computing User Group

10.29.2009

Expresiones Lambda en VB.NET 9.0

Explorando un poco las nuevas facilidades del lenguaje VB.NET en el framework 4.0, me encontré con algo que realmente me llamó la atención positivamente: expresiones lambda. Una de las formas de aprovechar las expresiones lambda es utilizandolas en las extensiones de métodos que tienen diversas clases, las cuales nos permiten de forma sencilla realizar operaciones que normalmente tomarían muchas líneas de código. Veamos el siguiente ejemplo:

En versiones anteriores se podía en VB.NET – y también en C# – utilizar la extensión del método FindAll de una lista para obtener una sub lista con todos los ítems que hicieran match con el criterio del predicado enviado por parámetro al método de extensión. El predicado de esta función, por lo general es un delegate que apunta a un método definido en otro lugar, o es un método anónimo. El siguiente código nos muestra esta situación:

image

Como podemos ver en la figura, tenemos una lista de enteros la cual se inicializa de 1 a 10. Seguidamente vamos a crear otra lista de enteros y la vamos a inicializar solamente con los números pares de la lista inicial. Esto lo logramos utilizando un predicado en el método de extensión FindAll de la clase List(Of T ), este predicado contiene la dirección de un método el cual se va a ejecutar por cada ítem contenido en la lista.

Si usamos una expresión lambda, el método será un poco más sencillo de escribir, tal y como podemos ver en el siguiente código:

image

El método anterior funciona de forma idéntica al método en donde utilizamos un delegate, pero no tiene una referencia a otro método que haga la operación deseada, en cambio la expresión lambda escrita como predicado del método FindAll se ejecuta de la misma manera que se ejecuta el delegate a la función ObtenerPares.

10.11.2009

Webcasts – EntityFramework y Mashups

En esta ocasión voy a darles solamente un link de un par de videos en el que tuve la suerte de participar en conjunto con Jose Guay de Guatemala, Carlos Lone de Guatemala y Ricardo Jiménez de Microsoft Costa Rica. El primer video es una conversación que tuvimos acerca al entity framework. El segundo video es acerca de mashups. Espero lo disfruten.

Aqui esta el link del entity framework y el otro link respecto a mashups.

Technorati Tags: ,

9.27.2009

Entity Framework: Eliminando Entidades de una Lista y Refrescando el UI

En el post anterior vimos como implementar la interface IEquatable<T> para poder utilizar los métodos de la lista sobre las entidades tales como Contains e IndexOf. En este post vamos a ver como eliminar entidades de la lista y notificar este evento al UI que tenga binding con la lista afectada. Al mismo tiempo vamos a aplicar la modificación a la base de datos.

Eliminando una Entidad de la Lista y Notificando el UI

El primer paso para eliminar una entidad de la lista que tenemos ligada a nuestro UI es definir como vamos a llevar a cabo este procedimiento. En primera instancia vamos a agregar dos botones más a nuestra pantalla, uno para eliminar y otro para aplicar cambios. El diseño de la pantalla quedará como se observa a continuación

image

El siguiente paso es cambiar la forma en que hacemos binding de los datos desde el EF. Anteriormente utilizabamos una lista para almacenar nuestras entidades y así presentarlas en el UI, ahora vamos a cambiar esa lista por una colección del tipo ObservableCollection. Las colecciones de este tipo tienen la particularidad que notifica cuando se agrega o se elimina un elemento de la colección, o cuando se recarga la misma. Para esto, declaramos la colección del tipo de la entidad Empresa como lo hicimos en el post anterior.

ObservableCollection<Empresa> m_Empresas = new ObservableCollection<Empresa>();

public ObservableCollection<Empresa> Empresas
{
get { return m_Empresas; }
set { m_Empresas = value; }
}


El siguiente paso es hacer el binding desde el EF y ligarlo con el control a través del cual queremos desplegar los datos. En nuestro caso tenemos una función que nos devuelve la colección de empresas – ObtenerEmpresa – y en el load de la forma, procedemos a ligar la colección al Grid de Empresas.



private void Window_Loaded(object sender, RoutedEventArgs e)
{
Empresas = ObtenerEmpresas();
dgEmpresas.ItemsSource = Empresas;
}
public ObservableCollection<Empresa> ObtenerEmpresas()
{
UseCasesEntities entities = GetEntity();
var Empresas = from e in entities.Empresa select e;
return new ObservableCollection<Empresa>(Empresas.ToList());
}



El método GetEntity() es un método que utiliza un patrón singleton para obtener siempre el mismo contexto del Entity Framework y así poder eliminar, modificar, o agregar entidades al repositorio de datos.



static UseCasesEntities entities;

private static UseCasesEntities GetEntity()
{
if (entities == null)
entities = new UseCasesEntities();
return entities;
}



El siguiente paso es agregar el código necesario para poder eliminar la entidad de la colección cuando el usuario así lo requiere, es decir cuando seleccione una entidad y de clic en el botón de eliminar. En este caso obtenemos la entidad seleccionada casteando la fila seleccionada a un objeto tipo Empresa, seguidamente y gracias a la implementación de IEquatable<T> podemos utilizar el método remove de la colección para remover la entidad de la colección. También procedemos a marcar el objeto seleccionado como eliminado dentro del contexto del entity framework.



private void btnEliminar_Click(object sender, RoutedEventArgs e)
{
Empresa tmpEmpresa = dgEmpresas.SelectedItem as Empresa;
Empresas.Remove(tmpEmpresa);
GetEntity().DeleteObject(tmpEmpresa);
}



Con estos cambios, ya tenemos la funcionalidad a nivel de UI, si ejecutamos el código anterior, vamos a eliminar los ítems de la lista, y sin refrescar la lista, obtenemos el cambio en el UI.



Aplicando los cambios en el UI



Una vez realizados los cambios en el UI, debemos persistir los cambios en la base de datos. Para llevar a cabo esta funcionalidad, simplemente agregamos el siguiente código al manejador del evento clic del botón aplicar.



private void btnAplicar_Click(object sender, RoutedEventArgs e)
{
GetEntity().SaveChanges();
}





En este caso, solamente ejecutamos el método SaveChanges para persistir el cambio o los cambios a la base de datos.



9.12.2009

Extendiendo el Entity Framework – Comparación y Búsqueda de Entidades

Una de las tareas más comunes cuando trabajamos con el Entity Framework es la búsqueda de las entidades en una lista y la comparación de las mismas. El EF nos provee la facilidad de agregar código para comparación a través de la Interface IEquatable y las clases parciales.

Interface IEquatable<T>

La interface IEquatable<T> de acuerdo al msdn se define como una interface que define un metodo de igualdad, el cual determina la igualdad de las instancias del tipo implementado. Por otro lado y para aclarar por adelantado, la Interface IComparable<T> define un metodo de comparación generalizado para ordenamiento de instancias.

IEquatable<T> se usa normalmente por colecciones genericas tales como List<T> y LinkedList<T> para ser utilizado en métodos tales como Contains, IndexOf, Remove, etc. Esta interface se debe de implementar en cualquier objeto que se va a almacenar en colecciones genéricas.

Extendiendo una Entidad con IEquatable<T>

El primer paso para extender una entidad del Entity Framework es crear una clase que contenga este código adicional. En este caso, vamos a extender la entidad Empresa y por lo tanto, vamos a crear una clase parcial que igualmente se va a llamar empresa. Para esto procedemos a agregar la clase en el proyecto donde definimos el modelo del Entity Framework.

imageSeguidamente procedemos a poner la clase recién creada como pública y parcial; esto va a permitir que esta clase se compile en conjunto con la clase generada por el EF en una sola clase,  por lo que toda la funcionalidad que agregemos a esta clase será parte de la clase Empresa del EF. Además, por estar en una clase parcial, si tenemos que regenerar el modelo, no vamos a perder la lógica incluída.

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

namespace Samples
{
public partial class Empresa
{
}
}
Como podemos ver en la siguiente figura, la clase que genera el EF es también parcial y por lo tanto podemos agregar la funcionalidad que deseamos.


image Seguidamente procedemos a implementar la clase IEquatable<T> para poder definir como vamos a hacer las comparaciones en nuestra entidad. Nótese como el método definido en el contrato de la interface – Equals – recibe otra entidad de tipo empresa para llevar a cabo la comparación.



public partial class Empresa : IEquatable<Empresa>
{
#region IEquatable<Empresa> Members

public bool Equals(Empresa other)
{
//Aquí vamos a implementar nuestra comparación
return true;
}

#endregion
}



Para este caso especifico, quiero que la empresa se pueda comparar tanto por el campo Id como por el nombre, es decir, buscarla en la lista por nombre y buscarla por Id para cuando por ejemplo el item se selecciona desde un combo box.



public partial class Empresa : IEquatable<Empresa>
{
#region IEquatable<Empresa> Members

public bool Equals(Empresa other)
{
if (this.Id == other.Id || this.Nombre == other.Nombre)
return true;
return false;
}

#endregion
}



Como podemos ver, el método Equals contiene la definición de comparación que nosotros creamos conveniente para poder utilizar la entidad en nuestra lógica de negocios.



Ahora vamos a utilizar nuestra entidad para diferentes propósitos. Inicialmente vamos a tener una pantalla para buscar empresas por nombre tal y como luce a continuación.



image La idea es buscar entre las empresas del grid la que deseamos y desplegarla en un diálogo modal. Este dialogo que se presentará de forma modal es el siguiente:



imageEl siguiente paso es crear la lógica para presentar un detalle de una empresa en el dialogo anterior, lo cual hacemos con el siguiente código:



public partial class frmEmpresa : Window
{
private Empresa m_Empresa;

public Empresa EmpresaProp
{
get { return m_Empresa; }
set { m_Empresa = value; }
}

public frmEmpresa(Empresa pEmpresa)
{
InitializeComponent();
EmpresaProp = pEmpresa;
txtNombre.Text = EmpresaProp.Nombre;
txtDireccion.Text = EmpresaProp.Direccion;
txtTelefono.Text = EmpresaProp.Telefono;
txtEmail.Text = EmpresaProp.Email;
}

public frmEmpresa()
{
InitializeComponent();
}

private void btnCerrar_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}


Ahora vamos a programar el código necesario para buscar la entidad deseada en la lista que hemos cargado en el grid y si la encontramos, procedemos a invocar la forma anterior para presentar su detalle.



public partial class BuscarEmpresa : Window
{
List<Empresa> m_Empresas = new List<Empresa>();

public List<Empresa> Empresas
{
get { return m_Empresas; }
set { m_Empresas = value; }
}
public BuscarEmpresa()
{
InitializeComponent();
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
Empresas = ObtenerEmpresas();
dgEmpresas.ItemsSource = Empresas;

}

public List<Empresa> ObtenerEmpresas()
{
UseCasesEntities entities = new UseCasesEntities();
var Empresas = from e in entities.Empresa select e;
return Empresas.ToList();
}

private void btnBuscar_Click(object sender, RoutedEventArgs e)
{
Empresa empresaTmp = new Empresa();
empresaTmp.Nombre = txtEmpresa.Text;

if (Empresas.Contains(empresaTmp))
{

frmEmpresa frm = new frmEmpresa(Empresas[Empresas.IndexOf(empresaTmp)]);
frm.ShowDialog();
}
else
MessageBox.Show("Empresa no existe", "Mensaje");
}
}



El código que nos interesa es el código del evento click del botón buscar. Lo primero que hacemos es crear una instancia de la entidad empresa y proceder a asignarle el valor digitado por el usuario en el textbox. Seguidamente, vamos a pedirle a la lista de empresas ( declarada al inicio de la clase ) a través del método Contains, si tiene una entidad igual a la que le estoy enviando. Nótese que aunque no he cargado todos los campos, el llamado a Contains busca la implementación de la interface IEquatable<T> para hacer la búsqueda, por esta razón si digitamos el nombre de alguna empresa que exista, el método lo encuentra. Si el existe, el siguiente paso es desplegarlo en la pantalla de detalle pasándola por parámetro. Para lograr esta funcionalidad tenemos que ir a obtener la entidad de la lista, lo cual se logra con una combinación de un método de la lista – IndexOf - y el indexador de la misma []. IndexOf utiliza la comparación que nos provee la interface IEquatable<T>. El resultado al ejecutar el ejemplo anterior es el siguiente:



imageEn los post siguientes vamos a profundizar en este tema.













9.02.2009

SpellCheck en WPF

Una característica interesante que me encontré trabajando en el desarrollo de una aplicación WPF es la posibilidad de tener SpellCheck en la edición de texto en los controles TextBox y RichTextBox. Además, la forma de lograrlo es muy simple. Inicialmente se habilita la propiedad SpellCheck.IsEnabled="True" y se indica cual lenguaje se desea para hacer el spell check con la propiedad Language. La siguiente figura nos muestra como llevar a cabo esta configuración:

image Cuando ejecutamos la aplicación y escribimos palabras en español incorrectas, estas serán subrayadas con rojo y si le damos botón derecho sobre la palabra, un context menu nos hará sugerencias para reemplazar la palabra incorrecta.

image El diccionario que se utiliza para realizar este spellcheck en este momento soporta 4 lenguajes: inglés, español, francés y alemán. La lista de sugerencias son una copia del diccionario de Microsoft Office 2007 y al ser una copia, no se requiere tener instalado Office en la máquina.

Technorati Tags: ,,

8.30.2009

Manejo de Excepciones en WPF

En una ocasión estando desarrollando un proyecto en WPF con varios desarrolladores más, surgió la pregunta ¿Cómo manejar las excepciones en WPF? Y es que esta pregunta puede parecer sencilla, ya que como todos sabemos en .NET existe el manejo de excepciones a través de la estructura try … catch … finally. Sin embargo, cuando se esta trabajando en el UI de un proyecto en WPF y varios desarrolladores hacen y modifican eventos y procedimientos en las pantallas – validación, llamadas a lógica de negocios y manejo de errores – es importante saber como va a reaccionar la aplicación a errores no esperados en secciones de código en donde no se han programado bloques de control de errores. En otras palabras lo que se busca es una forma central de manejar las excepciones, tal y como se logra hacer de manera sencilla en ASP.NET cuando en el archivo web.config le indicamos a la aplicación que en caso de un error no previsto y no atrapado, despliegue el error en una página específica. Durante esta experiencia investigué cuál era el modo más cercano de lograr este comportamiento en WPF y este post el resultado de esta investigación.

En primera instancia, si existe un lugar central desde donde crear un método que nos permita manejar los errores que se disparen en la aplicación WPF y que no hayan sido manejados por bloques de try…catch previamente. Este lugar es en el archivo App.xaml.cs – en el caso de C#. En esta clase podemos definir un manejador de eventos para el evento de aplicación DispatcherUnhandledException el cual se va a disparar cada vez que ocurre un evento inesperado. A continuación el código de la clase App.

using System.Windows.Threading;



/// <summary>
///
Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
string errorMessage = string.Format("Ocurrió una excepción inesperada. {0}{1}"
, Environment.NewLine, e.Exception);
MessageBox.Show(errorMessage, "Error atrapado en el obj Application");
e.Handled = true;
}
}


En este caso vamos a necesitar agregar el namespace using System.Windows.Threading que es el namespace donde se encuentra declarado el tipo DispatcherUnhandledExceptionEventArgs el cual es el que vamos a utilizar como parámetro para manejar el error. Esta variable – e en nuestro caso – contiene una referencia a la excepción que no ha sido manejada y una bandera indicando si la excepción ha sido manejada o no. Es importante destacar que este evento se va a disparar solamente en el thread del UI, otras excepciones lanzadas desde otro thread no van a ser atrapadas – lo veremos en el ejemplo. En el archivo App.xaml, vamos a agregar el evento y su correspondiente manejador, el cual en nuestro caso es App_DispatcherUnhandledException.



image Seguidamente procedemos a agregar el código correspondiente en WPF y XAML. Primeramente vamos a agregar 3 botones, el primero de ellos no va a manejar la excepción y por lo tanto debe de ser atrapada en el manejador global de errores, el segundo de ellos atrapa la excepción localmente ya que tiene un bloque try … catch y el último lanza una excepción en otro thread, por lo tanto no es manejada en nuestro evento de manejo de errores global a la aplicación. El código en cs es el siguiente.



private void btnGuardar_Click(object sender, RoutedEventArgs e)
{
throw new NotImplementedException();
}

private void button1_Click(object sender, RoutedEventArgs e)
{
try
{
throw new NotImplementedException();
}
catch (NotImplementedException ex)
{

MessageBox.Show(ex.Message, "Error manejado en la ventana");
}
}

private void button2_Click(object sender, RoutedEventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += delegate
{
throw new NotImplementedException();
};
worker.RunWorkerAsync();
}



Del lado de XAML, agregamos los 3 botones que van a disparar los eventos anteriores.



image La pantalla en modo gráfico luce así:



image Al ejecutar el primer botón – el error se maneja en el App.xaml.cs - el resultado es el siguiente:



image Al utilizar el botón en donde se maneja el error localmente el resultado es el siguiente:



image





Por último, al lanzar una excepción en otro thread no se dispara ningún error y este no se maneja de forma global.



image



De esta manera podemos manejar de manera unificada las excepciones sin manejar en aplicaciones WPF.







Technorati Tags: ,,

8.25.2009

Manejo del Scope con Unity

Cuando se trabaja con IoC containers existe un factor que en muchas ocasiones se ignora a la hora de crear instancias dinámicamente: el scope del objeto que estamos creando. En este post vamos a analizar las opciones para el manejo del scope cuando utilizamos el Unity Application Block.

¿Qué es el Scope?

El scope – alcance – de un objeto es la cantidad de tiempo o las llamadas a los métodos en los cuales un objeto existe. Es decir, el scope es el contexto bajo el cual un identificador se refiere a la misma instancia. También podemos definir el scope como la cantidad de tiempo que el estado de un objeto persiste. Cuando el contexto del scope finaliza, cualquier objeto ligado a este scope queda fuera de alcance y no pueden inyectarse de nuevo en otras instancias.

El Scope y los IoC

La verdadera ventaja del scope en los IoC es que permite modelar el estado de los objetos de forma declarativa. Esto se logra diciendole al inyector que una llave en particular esta ligada a un scope, y por lo tanto se puede manipular la construcción y el lige entre objetos en el contexto del inyector.

El aplicar correctamente el manejo del scope significa que un código trabajando en un contexto particular no esta conciente del contexto en que se ejecuta. Es responsabilidad del inyector el administrar estos contextos. Esto significa que se tiene una separación entre la aplicación y la infraestructura, sino que también estos servicios pueden ser utilizado para muchos propósitos alternando simplemente el scope seleccionado. Para visualizar mejor esto vamos a trabajar con un ejemplo.

deptartment.Print("drojas", "Project Plan", injector.Resolve<Printer>());
deptartment.Print("jcalvo", "work items", injector.Resolve<Printer>());
deptartment.Print("palfaro", "todo's", injector.Resolve<Printer>());


Supongamos que en un departamento de una empresa trabajan 3 usuarios, y cada uno tiene un documento que mandar a imprimir. Basándonos en el ejemplo anterior podríamos decir que la impresora la utiliza primero drojas, seguidamente jcalvo y por último palfaro. Si la impresora es de poca capacidad y los documentos de drojas y jcalvo son muy grandes, puede ser que palfaro se quede sin tinta o sin hojas para imprimir.



image



En este caso el injector distribuye la tinta a través de la misma impresora – misma instancia - entre todos los que van imprimiendo. Este es un ejemplo del contexto: Todos los trabajadores del departamento comparten la misma área, y por lo tanto comparten la impresora. En este caso la impresora esta accesible a través de un scope del tipo singleton.





Otro ejemplo de contexto sería cuando cada uno de los trabajadores del departamento tienen su propia impresora. Teoricamente, si utilizamos el ejemplo anterior, podríamos decir que cada trabajador imprime en su impresora; y digo teoricamente porque esto no es absolutamente cierto, ya que si palafaro manda a imprimir dos veces el mismo documento, estaríamos utilizando dos impresoras diferentes:



deptartment.Print("drojas", "Project Plan", injector.Resolve<Printer>());



deptartment.Print("jcalvo", "work items", injector.Resolve<Printer>());



deptartment.Print("palfaro", "todo's", injector.Resolve<Printer>());



deptartment.Print("palfaro", "todo's", injector.Resolve<Printer>());



En este caso, estamos trabajando sin alcance, y lo que estamos diciendole al injector es que debe de crear una nueva instancia por llamado.



Controlando el Scope con Unity


El scope en Unity se puede controlar vía configuración o vía código. El contenedor de Unity administra la creación y la resolución de objetos basado en el scope que se especifica cuando se registra el tipo o de lo contrario se utiliza el scope por defecto – sin scope.



Cuando se registra un tipo utilizando el metodo RegisterType,  el comportamiento por defecto es crear una nueva instancia del tipo solicitado cada vez que se invoca el metodo Resolve o ResolveAll. El contenedor no mantiene guarda una referencia al objeto. Sin embargo, cuando se desea un comportamiento Singleton para los objetos que se van a instanciar, el contenedor mantiene una referencia a los objetos creados.



Cuando se registra un objeto existente utilizando el método RegisterInstance el comportamiento por defecto es que el contenedor tome la administración del tiempo de vida del objeto que se pasa como parámetro al objeto. Esto significa que el objeto se mantiene en el scope mientras el contenedor este en el scope; una vez que el contenedor salga del scope o cuando se elimina la instancia del contenedor explícitamente, el objeto registrado será inalcanzable.



Unity utiliza lo que se conoce como “lifetime managers” para controlar como se guardan las referencias a las instancias de los objetos y como el contenedor elimina estas instancias. Unity incluye 3 “lifetime managers” que pueden ser utilizados directamente en el código.





  1. ContainerControlledLifetimeManager: Unity retorna la misma instancia del tipo registrado cada vez que se llama al metodo Resolve, ResolveAll o cuando el mecanismo de dependencia inyecta instancias en otras clases. Este es el mecanismo para implementar un comportamiento Singleton. Este lifetime manager se utiliza por defecto para el metodo RegisterInstance si no se especifica algún otro. Si se desea un comportamiento singleton que se crea cuando se utiliza el método RegisterType, se debe de especificar de forma explícita.




  2. ExternallyControlledLifetimeManager: Este manager permite registrar tipos y objetos existentes en el contenedorm, pero mantiene una referencia “débil” a los objetos que se crean utilizando Resolve y ResolveAll. Unity retorna la misma instancia cuando se utilizan estos métodos, pero el contenedor no mantiene una referencia fuerte a los mismos luego de crearlos, por lo que el Garbage Collector puede eliminar los objetos si no existe código que mantenga una referencia fuerte a los objetos creados.




  3. PerThreadLifetimeManager: Unity retorna la misma instancia por thread del tipo registrado cada vez que se invoca el método Resolve o ResolveAll. Este lifetime manager implementan un singleton por thread, por lo tanto retorna diferentes objetos para cada thread.





    1. Si se utiliza el método RegisterType, Unity crea una nueva instancia la primera vez que se resuelve el tipo en un thread específico utilizando Resolve o ResolveAll. Las siguientes invocaciones retornan la misma instancia en el thread.




    2. Si se utiliza el método RegisterInstance, se obtiene el mismo comportamiento que ofrece el método RegisterType. Por esta razón no se recomienda utilizar el método RegisterInstance para registrar un objeto utilizando este lifetime manager.





A continuación vamos a ver el uso de estos lifetime managers. Inicialmente vamos a crear una interface que se llamará IPrinter la cual tiene un método para imprimir y una propiedad llamada Name donde vamos a almacenar el código hash de la instancia utilizada, esto nos permitira ver si la instancia es un singleton o no.



public interface IPrinter
{
string Name { get; set; }
string Print(string document);
}


Seguidamente vamos a crear dos clases que implementan esta interface: LaserPrinter e InkPrinter. Estas clases son las que vamos a registrar e instanciar utilizando Unity y sus lifetime managers.



public class LaserPrinter : IPrinter
{
public string Name { get; set; }
public LaserPrinter()
{
Name = this.GetHashCode().ToString();
}
public string Print(string document)
{
return "Imprimiendo el documento: " + document + " en laser";
}
}

public class InkPrinter : IPrinter
{
public string Name { get; set; }
public InkPrinter()
{
Name = this.GetHashCode().ToString();
}
public string Print(string document)
{
return "Imprimiendo el documento" + document + " en Tinta";
}
}



Seguidamente creamos en el método main, el código necesario para registrar y crear las instancias utilizando el contenedor de Unity.



static void Main(string[] args)
{
using (IUnityContainer unityContainer = new UnityContainer())
{
//La impresora laser la vamos a registrar como un singleton
unityContainer.RegisterType<IPrinter, LaserPrinter>("Laser", new ContainerControlledLifetimeManager());
//La impresora de tinta le vamos a dar un tiempo de vida pasajero, es decir, vamos a crear
//una instancia por llamado.
unityContainer.RegisterType<IPrinter, InkPrinter>("Ink");

//Impresora con hash propio
IPrinter printer = unityContainer.Resolve<IPrinter>("Ink");
Console.WriteLine(printer.Print("Tareas"));
//Impresora con singleton
IPrinter printer2 = unityContainer.Resolve<IPrinter>("Laser");
Console.WriteLine(printer2.Print("Errores"));
//Impresora con singleton
IPrinter printer3 = unityContainer.Resolve<IPrinter>("Laser");
//Impresora con hash propio
IPrinter printer4 = unityContainer.Resolve<IPrinter>("Ink");

Console.WriteLine(printer.Name);
Console.WriteLine(printer2.Name);
Console.WriteLine(printer3.Name);
Console.WriteLine(printer4.Name);
}
}



El resultado al ejecutar el código anterior es el siguiente:



image 



La pregunta que nos surge ahora es: ¿cuándo usar un singleton o cuando usar un alcance pasajero? Pues desde mi punto de vista, un buen lugar para utilizar un singleton es una capa de acceso a datos, ya que por lo general estas operaciones son unitarias y especificas – leer datos, escribir un dato – y no necesitamos realmente crear una nueva instancia para poder tener acceso a estos componentes. Igualmente, operaciones en donde las operaciones para inicializar un objeto son muy “pesadas” y en donde estas configuraciones de arranque son solo de lectura, son buenos candidatos para un singleton.



Technorati Tags: ,,,

8.15.2009

¿Por qué es importante el MSE – Managed Service Engine?

En muchas ocasiones cuando estoy en consultorias relacionadas con arquitecturas orientadas a servicios – SOA – tengo que hacer mucho enfasis en el hecho de que tener web services en la organización no significa que tengo una arquitectura orientada a servicios. Al mismo tiempo, se me consulta que papel juega el MSE en la transición hacia una arquitectura orientada a servicios. En este post voy a tratar de aclarar estas dos dudas.

Tener Servicios Web no es tener SOA

Existe la creencia errada respecto a que tener servicios web para ser consumidos tanto internamente como externamente, me da automáticamente una arquitectura orientada a servicios. En realidad cuando implementamos servicios web dentro de nuestra organización estamos creando una arquitectura que se conoce como punto a punto. Esto se puede notar si tenemos muchos servidores Web hospedando los servicios, y/o si tenemos que consumir servicios web de muchas otras organizaciones ya sean externas o internas. En la siguiente figura podemos ver esta arquitectura.

image

En la figura anterior, podemos ver que las aplicaciones hacen referencias directas a servicios que retornan funcionalidad de negocios de las aplicaciones que desean acceder, teniendo en sus referencias el servidor donde estan hospedados estos servicios, el uri del servicio y el contrato de la implementación del servicio. Esto nos pone en desventaja ya que si tenemos que mover algún servicio de servidor, tenemos que actualizar todos los consumidores del mismo, ya que hay una referencia directa al servicio a través del servidor. Peor aún, si estamos consumiendo servicios externos y nos cambian la dirección del servicio, nuestra aplicación no funcionará correctamente si no se nos notifica a tiempo.

Otro problema que tendríamos además del ruteo de los mensajes es el manejo de los errores. Al tener diversas fuentes de donde consumir los servicios, los errores se van a almacenar y administrar en cada uno de los servidores internos o externos, de forma tal que no podemos crear logs centralizados para identificar que sucede en caso de presentarse algún error.

Además, dentro de los patrones de una arquitectura orientada a servicios, el concepto de servicio web no es exclusivo para su implementación. Esto por que en realidad en una arquitectura orientada a servicios yo puedo integrarme con servicios que implementen protocolos diversos tales como HTTP(s), TCP, etc.

Como me ayuda el MSE a tener una Arquitectura Orientada a Servicios

Una de las razones principales por la cual las organizaciones adoptan una arquitectura orientada a servicios es por la promesa de una alta flexibilidad en las aplicaciones. Esta promesa viene del hecho de que una arquitectura SOA diseñada correctamente reduce el tiempo de construcción de las aplicaciones y de los nuevos requerimientos en las aplicaciones ya existentes.

El primer requerimiento de una aplicación SOA bien diseñada es que cualquier aplicación puede ser accesada vía servicios ya sea interna o externamente lo cual permitirá la reutilización.  Esto nos va a permitir desarrollar nuevas aplicaciones que requieran funcionalidad de las aplicaciones ya implementadas de forma más rápida y sencilla porque vamos a requerir menos código para tener acceso a la funcionalidad deseada. Sin embargo, si debo escribir cada servicio desde cero este requerimiento no se puede cumplir o cumplirlo sería muy costos en tiempo e inversión. Si se construyen estos servicios como aplicaciones aisladas, se van a crear servicios con funcionalidades duplicadas, será dificil tener un inventario de servicios disponibles y sus funcionaldiades, los logs de errores de los servicios estarían en cada uno de los servidores que almacenan el servicio, por citar alguno de los inconvenientes que tendríamos si no utilizamos una arquitectura orientada a servicios.

El segundo punto a tratar es que una arquitectura SOA bien diseñada tiene que tomar en cuenta es el cambio constante. En un ambiente empresarial SOA, los servicios tienden a cambiar mientras evolucionan. Estos cambios son de dos tipos: cambios en la interface y cambios en la implementación. El reto esta en encontrar una manera de convivir con la evolución de los servicios y el minimizar el efecto del cambio en los servicios en el consumidor de los mismos.

La pregunta que nos surge ahora es: ¿Qué rol juega el MSE en este escenario? Pues bien, el MSE nos permite llevar a cabo virtualización de servicios. La virtualización de servicios es un esquema de instalación y administración de servicios que nos brinda toda la “plomería” requerida por todos los servicios dentro de la organización. Esto le permite al desarrollador enfocarse en construir nueva funcionalidad y nos brinda una base de funcionalidad donde se requiere conectar con nueva funcionalidad.

Respecto al manejo de los cambios en los servicios, el MSE nos permite manejar este problema a nivel de operación. Este nos da la posibilidad de crear nuevas versiones de las operaciones existentes de los servicios. El MSE nos brinda esta funcionalidad por que el mantiene la interface de la operaciones del servicio conectada pero separada de su implementación, siendo este el principio básico para la virtualización de servicios. A través de la virtualización de servicios se pueden tener tantas versiones de la operación del servicio activas como sea necesarias, pero solamente una puede ser publicada a través del WSDL. Esta característica nos permite soportar la compatiblidad hacia versoines anteriores ya que los usuarios con versiones anteriores pueden serguir consumiendo el servicio y los nuevos usuarios usan el WSDL publicado del nuevo servicio, ambos casos sin complicación alguna. En el momento en que todos los clientes se muevan a la última versión del servicio, las versiones anteriores pueden ser desactivadas. La siguiente figura nos muestra la arquitectura del funcionamiento del MSE y sus funcionalidades en cada uno de los componentes que lo conforman.

image

Technorati Tags: ,,,

8.04.2009

Entendiendo el MSE – Managed Service Engine

Como comenté en un post anterior, el MSE es una herramienta open source que me permite obtener funcionalidad para poder administrar y llevar a cabo una transición entre una arquitectura punto a punto – o servicios web instalados en diversos servidores y web – a una arquitectura orientada a servicios ( SOA ). En este post ahondaré un poco más en los componentes del MSE.

El MSE esta formado de tres componentes principales: el service runtime engine, el catalogo de servicios, y la herramienta de administración para implementar la virtualización de los servicios. El service runtime engine esta implementado como un servicio de windows que administra un conjunto de instancias de hosting de servicios WCF que se configuran automáticamente de la información que se encuentra en el catalogo de servicios.

El MSE esta compuesto de tres componentes internos lógicos: el messenger, el broker y el dispatcher. El messenger es el responsable de la normalización de los mensajes. El broker recibe los mensajes normalizados y es el responsable de seleccionar la versión específica de la operación. El dispatcher es el responsable de la invocación del servicio real que se desea consumir. La comunicación entre estos componentes sucede a través de canales WCF, esto permite distribuirlos en varios servidores y acomodarlos a diferentes infraestructuras que se puedan requerir.

El catalogo de servicios – también conocido como el repositorio de metadatos – contiene los modelos que guían los servicios virtuales contenidos en el runtime del MSE. Lo servicios se importan utilizando la herramienta de administración. Luego de importar el metadata del servicio, se definen los servicios virtuales para el consumo de los clientes.

Cuando se define un servicio virtual, se inicia escojiendo y configurando un binding de WCF. Se puede seleccionar que protocolo utilizar, que características de seguridad habilitar, o cualquier otra característica que soporte el binding seleccionado. También se puede especificar otros comportamietnos para los servicios como inspección de mensajes, transformación, información de versión, y cuales políticas se deben aplicar obligatoriamente utilizando la misma técnica.

El repositorio de metadata esta implementado como una base de datos SQL Server tradicional. Los consumidores no interactúan directamente con la base de datos aunque los datos se pueden publicar con el propósito de ser descubiertos. El MSE mantiene una distinción entre la noción de repositorio y el registro público. El repositorio es donde se encuentran los datos que guían el runtime, y el registro es un almacén separado de metadata de los sevicios que se puede hacer disponible para descubrir y consumir desde afuera.

La siguiente figura nos muestra un diagrama general con la ubicación de algunas de las funcionalidades que están disponibles en el MSE.

image

Technorati Tags: ,,

7.26.2009

Versionando Aplicaciones – Unity – Parte 3

Continuando con la serie de post acerca de IoC – contenedores de dependency injection – en este post vamos a examinar Unity, el cual es un application block que esta disponible gratuitamente desde el sitio de codeplex o a través del sitio de pattern and practices.

Al igual que cualquier otro IoC container, lo que busca unity es desasociar o eliminar la dependencia que existe entre las clases y “mover” esa dependencia a las interfaces. La ventaja con esto en un IoC, es que básicamente al depender de una interface, podemos cambiar la implementación de esa interface en cualquier momento sin necesidad de recompilar la aplicación sino más bien a través de configuración – lo único que necesitamos es cumplir con el contrato.

Trabajando con Unity

En esta ocasión vamos a implementar el mismo ejemplo que presentamos con CastleWindsor del cual presentamos el modelo a continuación:

image El primer paso para hacer funcionar Unity es agregar las referencias necesarias para tener acceso a Unity.

image

Una vez agregadas las referencias, vamos a construir el código necesario para crear la instancia de la clase DoSearch con la alerta del tipo IAlert instanciada utilizando Unity.

image En el código anterior, procedemos a registrar un tipo para el contrato IAlert, en este caso SMSAlert, lo cual nos permite crear una instancia de la clase SearchManager y proceder a asignarle la alerta que corresponde, en este caso utilizamos el metodo Resolve del contenedor. Cuando ejecutamos el código anterior, Unity sabe cual clase tiene que instanciar y procede como se muestra en la siguiente figura.

image El ejemplo anterior no es muy funcional en el sentido de que solamente tenemos una clase para registrar y por lo tanto a la hora de resolver cual clase instanciar, el contenedor solamente debe de instanciar la clase default registrada con el tipo. En el siguiente ejemplo vamos a registrar ambas implementaciones de IAlert con lo cual tendremos que elegir que instancia crear en tiempo de ejecución. Si registramos otro tipo despues de la alerta SMS, entonces el tipo que se instanciaría sería el último registrado.

image El resultado sería el siguiente:

image

La solución para poder elegir cual clase instanciar es especificar un nombre para cada mapa que se va a crear, y a la hora de crear la instancia procedemos a elegir vía ese nombre de mapa, cual tipo instanciar.

image

En este caso especificamos los nombres de SMS y EMail para los mapas y decidimos utilizar SMS. El resultado es el siguiente:

image

Con lo especificado hasta este momento, podemos crear un software factory muy sencillo basándonos en el nombre de la etiqueta del mapa y guardando el nombre en un archivo de configuración o algún medio que permita cambiar la clase a instanciar en tiempo de ejecución.

Pese a lo anterior, Unity nos permite registrar los tipos que vamos a utilizar en un archivo .config y crear las instancias en base a los registrios de los tipos hechos en este archivo. El siguiente ejemplo nos muestra como llevar a cabo esta tarea.

image

En primera instancia se deben agregar las referencias para poder acceder a la configuración del app.config – System.Configuration – y a la configuración de Unity – Unity.Configuration.

image  El siguiente paso es codificar la instanciación de la clase deseada. Para esto, accedemos al archivo de configuración a través del ConfigurationManager y procedemos a configurar la sección de Unity. Seguidamente creamos la clase y procedemos a resolver el tipo. Nótese que en este caso, le indicamos a Unity a través del método Resolve, que queremos una instancia con la etiqueta “SMS”, la cual vamos a agregar al archivo config seguidamente.

image

Primeramente procedemos a registrar la sección que vamos a llamar unity – podríamos llamarla como queramos – y vamos a indicar que assembly para configuración de Unity vamos a utilizar.

Seguidamente procedemos a crear “alias” de los contratos que vamos a instanciar – en este caso IAlert. Por último, dentro de la sección container, agregamos los tipos mapeados para poder instanciarlos. Como podemos ver, en este caso mapeamos SMSAlert a IAlert y le pusimos de nombre SMS, el cual es el nombre que vamos a utililizar para crear la instancia. El nombre PruebaCastleWindsor es el nombre del assembly que se genera y en donde residen los tipos – en este caso una aplicación de consola – y lleva ese nombre porque en el mismo proyecto donde estoy haciendo uso de Unity, hice la prueba de CastleWindsor. El resultado al ejecutar la aplicación es el siguiente:

image

Como hemos visto, Unity también nos sirve para crear aplicaciones fáciles de versionar en tiempo de ejecución – al decir versionar me refiero a instanciar los componentes de negocio que necesitamos dependiendo de reglas de configuración pre establecidas. En post posteriores vamos a ahondar en el uso de Unity.

Technorati Tags: ,,