Hola a todos, siguiendo con los artículitos de WCF, os vengo a hablar de una solución que implementamos en un cliente para pasar información a través de su parte servidora sin tener que tocar la firma de los métodos, porque había unos cuantos. Esto se implementó a través del OperationContext que nos ofrece la activación del servicio WCF y la verdad es que funciona de vicio. Pero cómo me dijo un gran crack sobre esto, hay que tener cuidado con el OperationContext porque no deja de ser una sesión de servidor, pero es finita y se sabe en qué momento se invalida y se crea. Os paso a contar el problema que teníamos…
El problema
Bueno, el problema era más o menos sencillo, en la solución implementada existían entidades de datos muy, muy, muy pesadas y obtenerlas consumía mucho tiempo de base de datos e impactaba muchísimo en el rendimiento de la aplicación. Cómo la solución tenía una sesión de servidor ya implementada (cosa que ya quitamos), pues se metió una especie de cache que se creaba cuando se iniciaba la llamada al servicio y se destruía cuando se terminaba la ejecución del servicio. Pero estaba construida de aquella manera y cuando se sometió a pruebas de concurrencia… en fin, podría haber salido mejor.
¿Qué necesitabamos?
La necesidad era poder pasar las entidades que ya se habían obtenido de un método a otro, o de una capa a otra del servidor, para no tener que volver a obtenerlas una y otra vez. La respuesta clara y más sencilla… pasemos esa información en la llamada a los métodos. Después vimos que había que tocar muchos, muchos, muchos métodos y se descartó por tiempo y esfuerzo 🙁
La solución que implementamos
Un compañero muy listo que tengo me dijo “oye, mira a ver si en el contexto de operación puedes pasar información personalizada”, así que me puse manos a la obra y encontré que se puede, vaya si se puede, a través de la interfaz IExtension. La verdad es que se pasa una hashtable (nos encantan las hashtables, tenemos kilo y medio de ellas) con la información que queremos, no es muy bonito, de hecho es feote, pero funciona (esta frase es uno de los peores males en esto de la programación…).
Para hacer esto, creamos una clase que implemente la interfaz IExtension<IContextChannel>, porque queremos almacenar la información en el canal, y tenemos que implementar los métodos “Attach” y “Detach”.
Algo parecido a esto
using System.Collections;
using System.ServiceModel;
namespace TestIExtension
{
public class ExtensionTest : IExtension<IContextChannel>
{
Hashtable mHash = null;
public Hashtable Hash
{
get { return mHash; }
set { mHash = value; }
}
#region IExtension<IContextChannel> Members
public void Attach(IContextChannel owner)
{
if (mHash == null)
{
mHash = new Hashtable();
}
}
public void Detach(IContextChannel owner)
{
}
#endregion
}
}
Pensad que en vez de una hashtable en modo cajón desastre, se puede poner cualquier tipo de información.
Para utilizar esta extensión en vuestro código, para recoger la información o para insertarla tendremos que utilizar el siguiento código:
if (OperationContext.Current != null &&
OperationContext.Current.Channel != null &&
OperationContext.Current.Channel.Extensions != null)
{
TestIExtension testExtension = OperationContext.Current.Channel.Extensions.Find<TestIExtension>();
if (testExtension != null)
{
return cacheExtension.Hash;
}
}
Como esta información está “viva” durante toda la activación del servicio, da exactamente igual desde que “capa” llamemos a este código porque siempre estará disponible.
Otra cosa que encontramos que estaba bastante bien, es que aunque los servicios estén en modo Single, esta información se genera en cada llamada al servicio. Cosa totalmente lógica y normal, pero bueno en esto nunca se sabe :).
Conclusiones
WCF mola!!!! y el contexto de operación está genial y se le pueden hacer mil y una perrería, pero si me queda una cosa clara es que, la información que necesite un método se le debería pasar siempre por parámetros, vamos que un método debería disponer de toda la información que necesita de forma explícita y así no llevar a ninguna confusión, esto puede no ser cierto en todos los casos, pero en la medida de lo posible la simplicidad ayuda mucho (Keep it simple!!!!).
Saludicos.