sábado, 3 de julio de 2010

WCF e Inyección de dependencias (WCF & DI)

La pregunta es ¿Puedo usar Inyección de dependencias
con WCF?

La respuesta es .

¿Necesito Unity spring, etc, etc para esto? Pues la verdad es que NO.

¿Y esto como se come? Sencillo. WCF está basado en interfaces. Para definir el contrato de datos y el contrato de servicio, definimos una interfaz que implementa ambos (curiosamente igual que cualquier patrón de DI - Inyección de dependencias).

¿Y esto para qué sirve?
Pues resulta muy útil cuando quieres trabajar con objetos diferentes en dos módulos conectados a través de WCF. Los objetos (o más bien el contrato de datos) pueden ser diferentes siempre y cuando cumplan la interfaz definida para el servicio WCF.

Os cuento la raíz del problema. Hace algunas semanas me encontré un planteamiento usando WCF: resulta que necesitaba enviar información de un servidor A a otro servidor B. Resulta que el servidor B usa un objeto idéntico al manejado en A,pero con alguna propiedad más.

La solución a simple vista (y sin pensar demasiado) pasa por mandar los datos de A a B y mapear en un nuevo objeto. Esta solución me planteaba el siguiente problema:

En el servidor A, rellenaba el contrato de datos solicitado por B, lo enviaba y B lo recibía y mapeaba en un nuevo objeto. Esto significa que en algún momento tendría que tener dos objetos cargados en memoria y además perder tiempo en realizar la copia del contrato a mi objeto de trabajo. Por tanto el proceso sería algo así:

1. Rellenar contrato de datos
2. Serializar con

trato de datos
3. Enviar contrato de datos
4. Deserializar contrato de datos
5. Copiar datos del contrato al objeto local (mapping).

De esta manera, la cargabilidad del sistema queda reducida, ya que necesito consumir recursos y tiempo para esta tarea. Andaba yo pensando que sería mucho mejor si no tengo que mapear de un objeto a otro (dichosos mapeos). ¿Y si pudiese deserializar el objeto de origen en uno nuevo con una estructura similar pero más propiedades que el anterior?
Curiosamente andaba yo dando vueltas al patrón de inyección de dependencias y además me enfrentaba a este problema y… curiosamente WCF se configura en base a una interfaz. Así que si juntamos y agitamos ambas ideas sale un curioso coctel. El proceso se convierte en lo siguiente:


1. Rellenar contrato de datos
2. Serializar contrato de datos
3. Enviar contrato de datos
4. Deserializar contrato de datos

Veamos un ejemplo:
Creamos un servicio WCF desde cero en Visual Studio y lo dejamos tal cual. Este contrato tiene dos propiedades.
Creamos una aplicación de consola y agregamos la referencia Web.
Y ahora viene lo interesante:
En el proyecto de consola, localizamos el fichero Reference.cs donde está definida la estructura de nuestro DataContract:

Localizamos las propiedades:

        [System.Runtime.Serialization.OptionalFieldAttribute()]
private bool BoolValueField;

[System.Runtime.Serialization.OptionalFieldAttribute()]
private string StringValueField;

y añadimos una más:

public int UnNumero
{
get;
set;
}

Ahora tenemos el mismo contrato con una propiedad más.
Escribimos el código en el fichero Program.cs de la aplicación de consola para llamar al servicio:

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

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
ServiceReference1.ServiceClient cliente = new ServiceReference1.ServiceClient();
ServiceReference1.CompositeType entrada = new ServiceReference1.CompositeType();

entrada.StringValue = "Hola";
entrada.UnNumero = 4;
entrada.BoolValue = true;

entrada=cliente.GetDataUsingDataContract(entrada);

Console.WriteLine(entrada.StringValue);
Console.WriteLine(entrada.UnNumero);
Console.WriteLine(entrada.BoolValue);
Console.ReadLine();
}
}
}

Podemos ver que tengo la propiedad numérica añadida y el servicio puede modificar los datos de nuestro objeto.
El resultado de ejecutar este proyecto es el siguiente:
Hola
0
true
Humm, quizá no era el resultado esperado. Según este resultado sí puedo extender el objeto pero los datos en el contenidos serán eliminados si los relleno antes de invocar al servicio.


Bueno, espero que sea de utilidad।

No hay comentarios:

Etiquetas