O WCF provê três modelos diferente de controle de instâncias, sendo estes modelos:
Per call instance mode – Uma nova instância do serviço WCF é criada para cada chamada de método invocada por um cliente e destruida após a resposta ser enviada.
Per session instance mode – Apenas uma instância de um serviço é criada para um conjunto de integrações com o cliente. A instância do serviço só é destruída quando o cliente termina suas requisições.
Single instance mode – Uma instância global do serviço é criada, e desta forma fica responsável por receber e processar todas as requisições de todos os clientes.
A enumeração InstanceContextMode é utilizada para indicar qual modelo de instâncias será utilizado pelo serviço durante o seu funcionamento. Ela determina qual associação deve existir entre o canal e o serviço.
Mas, para manter a instância de um serviço ativa, apenas alterar o modo de controle de instâncias não é suficiente. Para associar um cliente com uma instância particular do WCF, é preciso que o WCF consiga identificar o cliente que fez o invoque do método. Um modo de fazer isso é utilizar uma transport-level session, isto é, uma conexão contínua, tais como as mantidas pelos protocolos TCP e IPC.
Desta maneira, para mantermos uma sessão ativa entre o cliente e o serviço WCF, é preciso usar um binding como NetTcpBinding ou NetNamedPipeBinding. O WsHttpBinding também pode ser utilizado, pois ele é capaz de emular uma transport-level session, pois utiliza um ID de sessão no cabeçalho das mensagens, para identificar exclusivamente cada cliente. Em contrapartida, o BasicHttpBinding não pode ser utilizado, pois ele recria uma conexão sempre, o que impede a identificação do cliente pelo serviço WCF.
Neste post demonstro um exemplo de como manter a instância de um serviço durante múltiplas chamadas de método para um cliente. Neste exemplo configurei o serviço para utilizar WsHttpBinding. Os blocos necessários para implementação do serviço estão distribuídos a seguir.
Configuração do WsHttpBinding
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="NewBehavior">
<serviceDebug />
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="NewBehavior" name="WcfHostService.StatusService">
<endpoint address="" binding="wsHttpBinding" contract="WcfHostService.IStatusService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
Código do Serviço
[DataContract]
public enum Status {
[EnumMember]
Stopped = 1,
[EnumMember]
Initializing = 2,
[EnumMember]
Processing = 3,
[EnumMember]
Ready = 4
}
[ServiceContract]
public interface IStatusService {
[OperationContract]
void ChangeStatus(Status newStatus);
[OperationContract]
Status GetCurrentStatus();
[OperationContract]
int GetNumberOfInteractions();
}
[ServiceKnownType(typeof(Status))]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class StatusService : IStatusService {
private Status _currentStatus;
private int _interactions;
public StatusService() {
this._currentStatus = Status.Stopped;
this._interactions = 0;
}
public void ChangeStatus(Status newStatus) {
this._interactions++;
this._currentStatus = newStatus;
}
public int GetNumberOfInteractions() {
return this._interactions;
}
public Status GetCurrentStatus() {
return this._currentStatus;
}
}
Código da Camada Cliente
static void Main(string[] args) {
int interactions = 0;
var client = new StatusService.StatusServiceClient();
// Change status to Initializing
client.ChangeStatus(StatusService.Status.Initializing);
interactions = client.GetNumberOfInteractions();
Console.WriteLine("Current status is: " + client.GetCurrentStatus());
Console.WriteLine("Interaction number: " + interactions);
// Change status to Processing
client.ChangeStatus(StatusService.Status.Processing);
interactions = client.GetNumberOfInteractions();
Console.WriteLine("Current status is: " + client.GetCurrentStatus());
Console.WriteLine("Interaction number: " + interactions);
// Change status to Ready
client.ChangeStatus(StatusService.Status.Ready);
interactions = client.GetNumberOfInteractions();
Console.WriteLine("Current status is: " + client.GetCurrentStatus());
Console.WriteLine("Interaction number: " + interactions);
}
Por
MSc. Fernando Henrique Inocêncio Borba Ferreira.
Microsoft Most Valuable Professional – Visual C#
Referências:
http://www.codeproject.com/Articles/86007/3-ways-to-do-WCF-instance-management-Per-call-Per
http://msdn.microsoft.com/pt-br/library/system.servicemodel.instancecontextmode.aspx