Cuando creamos un servicio con Windows Communication Foundation, debemos conocer el comportamiento que queremos que tenga en cuanto a sus instancias se refiere. Para controlar el tiempo de vida del contexto disponemos de los siguientes modos:
- PerCall: Cada cliente creará una nueva instancia por llamada al servicio.
- PerSession: Se genera una instancia por sesión.
- Single: Se utiliza la misma instancia para todas las peticiones independientemente del cliente.
Como he encontrado mucha literatura al respecto y los ejemplos han sido prácticamente el mismo en todos los sitios, he creado uno personalizado donde se realiza el envío de tweets e intento recuperar los mismos utilizando los distintos modos.
Creo un proyecto de tipo WCF Service Library:
Elimino tanto la clase y la interfaz generada por la plantilla y creo una clase Tweet.cs con el rol de DataContract.
using System.Runtime.Serialization; namespace InstanceContextModeWCF { [DataContract] public class Tweet { [DataMember] public int Id { get; set; } [DataMember] public string User { get; set; } [DataMember] public string Message { get; set; } } }
Una interfaz como ServiceContract:
using System.Collections.Generic; using System.ServiceModel; namespace InstanceContextModeWCF { [ServiceContract] public interface ITwitter { [OperationContract] void SendTweet(Tweet tweet); [OperationContract] List<Tweet> GetMyTweets(); } }
Y por último la clase que implementa nuestro contrato.
using System.Collections.Generic; using System.ServiceModel; namespace InstanceContextModeWCF { //[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] //[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] //[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] public class Twitter : ITwitter { private readonly List<Tweet> _tweets = new List<Tweet>(); public void SendTweet(Tweet tweet) { _tweets.Add(tweet); } public List<Tweet> GetMyTweets() { return _tweets; } } }
En la clase Twitter he dejado comentadas las tres posibilidades. ¡Veamos cada una de ellas!
PER CALL
Cuando activamos el modo PerCall nuestro servicio se comportará de la siguiente manera: Creará una instancia para realizar la llamada al método solicitado y, una vez que haya finalizado la llamada, destruirá la instancia creada.
Para este primer ejemplo he activado la primera línea comentada y he seguido los pasos en el orden que señalo en la imagen. Como podemos ver, he creado una conexión con el programa que está actuando como servidor, he rellenado el apartado de mensaje y he enviado el mismo. En este caso, no ha sido posible recuperar el tweet al realizar una nueva llamada con PerCall.
PER SESSION
Con PerSession vamos a utilizar la misma instancia hasta que la sesión finalice. Es decir, un cliente crea un canal y tiene la posibilidad de realizar distintas llamadas a distintos métodos dentro del mismo contexto. Siguiendo el mismo ejemplo, habilitando la segunda línea y deshabilitando la primera, realizamos las mismas acciones desde el cliente.
Como la instancia permanece con vida durante toda la sesión, el cliente es capaz de poder enviar un tweet y después recuperarlo. Sin embargo, si nosotros pulsamos sobre Disconnect e intentamos recuperar el tweet enviado a través del botón Get All!, la información ya habrá desaparecido al haber creado una nueva sesión.
private void btnConnect_Click(object sender, EventArgs e) { _channel = new ChannelFactory<ITwitter>("TwitterService"); _client = _channel.CreateChannel(); lblState.Text = "Connected!"; lblState.ForeColor = System.Drawing.Color.Blue; } private void btnDisconnect_Click(object sender, EventArgs e) { _channel.Close(); lblState.Text = "Disconnected!"; lblState.ForeColor = System.Drawing.Color.Red; }
SINGLE
El modo Single se utiliza para mantener una misma instancia desde la primera petición de un cliente cualquiera hasta que el servicio se ha parado completamente.
Si habilitamos el último modo comentado en el código, y deshabilitamos el anterior, podemos realizar los siguientes pasos:
Si cerramos y abrimos de nuevo el cliente, sin cerrar el programa servidor, y pulsamos de nuevo en Get All! descubrimos que nuestro tweet sigue con vida 😉