Desenvolvimento - WCF
WCF – Gerenciamento de Instância
O gerenciamento de instância é uma técnica utilizada pelo WCF que determina como e por quem as requisições dos clientes serão atendidas.
por Marcos Aguiar JrEsse artigo irá falar sobre gerenciamento de instância no WCF e para que você possa entender esse artigo é necessário ter um conhecimento básico em WCF.
Existem três formas de realizar requisições através de um serviço WCF.Essas formas são conhecidas como gerenciamento de instancia e ajudam a melhorar o desempenho e a segurança do WCF.
Antes de explicar cada gerenciamento de instância, vou mostrar abaixo o código fonte que vamos utilizar para os exemplos.Lembre-se é recomendado ter conhecimento em WCF.
Vamos utilizar um projeto Console. Primeiro vamos criar a seguinte Interface:
[ServiceContract]
public interface IContrato
{
[OperationContract]
int Contador();
}
Em seguida uma classe que é herdada dessa Interface com a implementação do método Contador:
[ServiceBehavior]
public class Contrato: IContrato
{
private int _intContador;
public int Contador()
{
return _intContador++;
}
}
Em Program.cs no método Main digite o seguinte código:
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(Contrato), new Uri[] { new Uri("net.tcp://localhost:9393") }))
{
host.Description.Behaviors.Add(new ServiceMetadataBehavior());
host.AddServiceEndpoint(typeof(IContrato), new NetTcpBinding(), "srv");
host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
host.Open();
Console.WriteLine("[ O Serviço está rodando ]");
Console.ReadLine();
using (ChannelFactory<IContrato> f = new ChannelFactory<IContrato>(new NetTcpBinding(), "net.tcp://localhost:9393/srv"))
{
var channel = f.CreateChannel();
for (int intContador = 0; intContador < 5; intContador++)
{
Console.WriteLine(channel.Contador().ToString());
}
}
using (ChannelFactory<IContrato> f = new ChannelFactory<IContrato>(new NetTcpBinding(), "net.tcp://localhost:9393/srv"))
{
var channel = f.CreateChannel();
for (int intContador = 0; intContador < 5; intContador++)
{
Console.WriteLine(channel.Contador().ToString());
}
}
Console.ReadLine();
}
Para esse exemplo estou criando o host e a chamada ao serviço em uma única aplicação, isso não é correto em um projeto, mas para um exemplo será útil. Depois de criar o host, crio dois proxy (instância do serviço) que realizaram cinco requisições cada um.
Bem com esse código pronto vamos às explicações.
PerSession
Esse é a instância padrão do WCF. Quando a aplicação cliente cria uma proxy, esse proxy ira realizar todas as conexões com o serviço que o cliente chamar, até que o método Close (ou Dispose) seja chamado e o proxy seja encerrado. Enquanto o proxy não for fechado todas as alterações feita nos membros internos do serviço (como em uma propriedade global como no nosso exemplo em _intContador) será armazenada. Caso a aplicação cliente crie dois proxy , cada proxy irá controlar sua memoria, não interferindo um proxy no outro.
Como já escrevi, o PerSession é a instancia default do WCF, nesse caso não precisamos informá-la quando desejamos utilizar, mas em nosso exemplo vamos especificar. Vamos dizer ao WCF para trabalhar com PerSession na classe do serviço (no nosso exemplo na classe Contrato), como exemplo abaixo:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
Ao executar nosso exemplo temos o seguinte resultado:
A propriedade _intContador é incrementada sempre que o proxy é chamado, porém quando o proxy é finalizado e uma novo proxy é criado, o _intContador começa do zero (propriedade int por padrão começa com valor zero), pois a instância anterior foi perdida.
PerCall
Diferente do PerSession o PerCall cria uma nova requisição do proxy, ou seja, quando a operação é finalizada o proxy é removido da memoria. Para utilizarmos o PerCall precisamos alterar na classe Contador o InstanceContextMode conforme exemplo abaixo:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
Ao executar nosso exemplo após a alteração, temos o seguinte resultado:
O resultado sempre será zero porque, apesar de realizar N requisições ao serviço a propriedade _intContador não é incrementada.
Single
Single tem uma maneira diferente de se comportar. Existir apenas uma única instancia do proxy que ira servir para todas as requisições, mesmo que o Close ou Dispose sejam chamados ou que um novo objeto proxy sejacriado. Para utilizarmos o Single precisamos alterar na classe Contador o InstanceContextMode conforme exemplo abaixo.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
Mesmo descartando o primeiro proxy, quando começamos a utilizar o segundo proxy o _intContador continua sendo incrementando com o valor que foi finalizado pelo primeiro proxy, conforme podemos ver na imagem abaixo:
Você deve-se perguntar qual é a melhor? Isso depende, ninguém melhor do que você para decidir qual tipo de gerenciamento de instância é a melhor para a sua solução.Só devemos tomar cuidado porque a instância está ligada ao binding, ou seja, nem todos os binding (como BasicHttpBinding) suportar esse exemplo que implementamos.
O código fonte desse exemplo está disponívelaqui.
Espero que tenham gostado e até a próxima.
Obrigado.