Partilhar via


Padrões de design: List-Based Publish-Subscribe

O exemplo ListBasedPublishSubscribe ilustra o padrão de Publish-Subscribe baseado em lista implementado como um programa WCF (Windows Communication Foundation).

Observação

O procedimento de configuração e as instruções de compilação para este exemplo estão localizados no final deste tópico.

O padrão de design de Publish-Subscribe baseado em lista é descrito na publicação Microsoft Patterns & Practices, Integration Patterns. O padrão Publish-Subscribe passa informações para uma coleção de destinatários que se inscreveram em um tópico de informações. A publicação-subscrição baseada em listas mantém uma lista de subscritores. Quando há informações para compartilhar, uma cópia é enviada para cada assinante da lista. Este exemplo demonstra um padrão dinâmico de publicação-assinatura baseado em lista, onde os clientes podem se inscrever ou cancelar a assinatura com a frequência necessária.

O exemplo de Publish-Subscribe baseado em lista consiste em um cliente, um serviço e um programa de fonte de dados. Pode haver mais de um cliente e mais de um programa de fonte de dados em execução. Os clientes subscrevem o serviço, recebem notificações e cancelam a subscrição. Os programas de fonte de dados enviam informações para o serviço para serem compartilhadas com todos os assinantes atuais.

Neste exemplo, o cliente e a fonte de dados são programas de console (arquivos.exe) e o serviço é uma biblioteca (.dll) hospedada no IIS (Serviços de Informações da Internet). A atividade do cliente e da fonte de dados é visível na área de trabalho.

O serviço usa comunicação duplex. O contrato de serviço ISampleContract é emparelhado com um contrato de retorno ISampleClientCallback. O serviço implementa operações de serviço de Assinatura e Cancelamento de Assinatura, que os clientes usam para ingressar ou sair da lista de assinantes. O serviço também implementa a PublishPriceChange operação de serviço, que o programa de fonte de dados chama para fornecer novas informações ao serviço. O programa cliente implementa a operação de serviço PriceChange, que o serviço utiliza para notificar todos os subscritores de uma alteração de preço.

// Create a service contract and define the service operations.
// NOTE: The service operations must be declared explicitly.
[ServiceContract(SessionMode=SessionMode.Required,
      CallbackContract=typeof(ISampleClientContract))]
public interface ISampleContract
{
    [OperationContract(IsOneWay = false, IsInitiating=true)]
    void Subscribe();
    [OperationContract(IsOneWay = false, IsTerminating=true)]
    void Unsubscribe();
    [OperationContract(IsOneWay = true)]
    void PublishPriceChange(string item, double price,
                                     double change);
}

public interface ISampleClientContract
{
    [OperationContract(IsOneWay = true)]
    void PriceChange(string item, double price, double change);
}

O serviço usa um evento .NET Framework como o mecanismo para informar todos os assinantes sobre novas informações. Quando um cliente ingressa no serviço chamando Subscribe, ele fornece um manipulador de eventos. Quando um cliente sai, desinscreve o seu manipulador de eventos do evento. Quando uma fonte de dados chama o serviço para relatar uma alteração de preço, o serviço gera o evento. Isso invoca cada instância do serviço, uma para cada cliente que se inscreveu, e causa a execução dos respetivos manipuladores de eventos. Cada manipulador de eventos passa as informações para seu cliente por meio de sua função de retorno de chamada.

public class PriceChangeEventArgs : EventArgs
    {
        public string Item;
        public double Price;
        public double Change;
    }

    // The Service implementation implements your service contract.
    [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
    public class SampleService : ISampleContract
    {
        public static event PriceChangeEventHandler PriceChangeEvent;
        public delegate void PriceChangeEventHandler(object sender, PriceChangeEventArgs e);

        ISampleClientContract callback = null;

        PriceChangeEventHandler priceChangeHandler = null;

        //Clients call this service operation to subscribe.
        //A price change event handler is registered for this client instance.

        public void Subscribe()
        {
            callback = OperationContext.Current.GetCallbackChannel<ISampleClientContract>();
            priceChangeHandler = new PriceChangeEventHandler(PriceChangeHandler);
            PriceChangeEvent += priceChangeHandler;
        }

        //Clients call this service operation to unsubscribe.
        //The previous price change event handler is unregistered.

        public void Unsubscribe()
        {
            PriceChangeEvent -= priceChangeHandler;
        }

        //Information source clients call this service operation to report a price change.
        //A price change event is raised. The price change event handlers for each subscriber will execute.

        public void PublishPriceChange(string item, double price, double change)
        {
            PriceChangeEventArgs e = new PriceChangeEventArgs();
            e.Item = item;
            e.Price = price;
            e.Change = change;
            PriceChangeEvent(this, e);
        }

        //This event handler runs when a PriceChange event is raised.
        //The client's PriceChange service operation is invoked to provide notification about the price change.

        public void PriceChangeHandler(object sender, PriceChangeEventArgs e)
        {
            callback.PriceChange(e.Item, e.Price, e.Change);
        }

    }

Ao executar o exemplo, inicie vários clientes. Os clientes subscrevem o serviço. Em seguida, execute o programa de fonte de dados, que envia informações para o serviço. O serviço transmite a informação a todos os assinantes. Você pode ver a atividade em cada console do cliente confirmando que as informações foram recebidas. Pressione ENTER na janela do cliente para desligar o cliente.

Para configurar e compilar o exemplo

  1. Verifique se você executou o procedimento de instalação do One-Time para os exemplos do Windows Communication Foundation.

  2. Para criar a edição C# ou Visual Basic .NET da solução, siga as instruções em Criando os exemplos do Windows Communication Foundation.

Para executar a amostra na mesma máquina

  1. Teste se você pode acessar o serviço usando um navegador digitando o seguinte endereço: http://localhost/servicemodelsamples/service.svc. Uma página de confirmação deve ser exibida em resposta.

  2. Execute Client.exe de \client\bin\, sob a pasta específica do idioma. A atividade do cliente é exibida na janela do console do cliente. Lançar várias aplicações cliente.

  3. Executar Datasource.exe a partir de \datasource\bin\, na pasta específica do idioma. A atividade da fonte de dados é exibida na janela do console. Uma vez que a fonte de dados envia informações para o serviço, elas devem ser passadas para cada cliente.

  4. Se o cliente, a fonte de dados e os programas de serviço não puderem se comunicar, consulte Dicas de solução de problemas para exemplos de WCF.

Para executar o exemplo em várias máquinas

  1. Configure a máquina de atendimento.

    1. Na máquina de serviço, crie um diretório virtual chamado ServiceModelSamples. Os ficheiros de lote Setupvroot.bat do Processo de Instalação doOne-Time para os Samples da Windows Communication Foundation podem ser utilizados para criar o diretório de disco e o diretório virtual.

    2. Copie os arquivos de programa de serviço de %SystemDrive%\Inetpub\wwwroot\servicemodelsamples para o diretório virtual ServiceModelSamples na máquina de serviço. Certifique-se de incluir os arquivos no diretório \bin.

    3. Teste se você pode acessar o serviço da máquina cliente usando um navegador.

  2. Configure as máquinas cliente:

    1. Copie os arquivos de programa cliente da pasta \client\bin\, na pasta específica do idioma, para as máquinas cliente.

    2. Em cada arquivo de configuração do cliente, altere o valor de endereço da definição de ponto de extremidade para corresponder ao novo endereço do seu serviço. Substitua quaisquer referências a "localhost" por um nome de domínio totalmente qualificado no endereço.

  3. Configure a máquina da fonte de dados:

    1. Copie os ficheiros do programa da fonte de dados da pasta \datasource\bin\, dentro da pasta específica do idioma, para a máquina da fonte de dados.

    2. No arquivo de configuração da fonte de dados, altere o valor de endereço da definição de ponto de extremidade para corresponder ao novo endereço do seu serviço. Substitua quaisquer referências a "localhost" por um nome de domínio totalmente qualificado no endereço.

  4. Nas máquinas cliente, inicie Client.exe a partir de um prompt de comando.

  5. Na máquina de origem dos dados, inicie Datasource.exe a partir de um prompt de comando.