Шаблоны проектирования: List-Based Publish-Subscribe

Пример ListBasedPublishSubscribe иллюстрирует шаблон на основе списка Publish-Subscribe, реализованный как программа на базе Windows Communication Foundation (WCF).

Замечание

Процедура установки и инструкции по сборке для этого примера находятся в конце этого раздела.

Шаблон проектирования на основе списка Publish-Subscribe описан в публикации Microsoft Patterns и Practices, шаблонах интеграции. Шаблон Publish-Subscribe передает информацию группе получателей, подписавшихся на информационную тему. Система публикации-подписки на основе списка поддерживает список подписчиков. При наличии сведений для обмена, копия отправляется каждому подписчику в списке. В этом примере показан шаблон публикации на основе динамического списка, где клиенты могут подписываться или отменять подписку по мере необходимости.

Пример Publish-Subscribe на основе списка состоит из клиента, службы и программы источника данных. Может быть более одного клиента и более одной программы источника данных. Клиенты подписываются на службу, получают уведомления и отменяют подписку. Программы источника данных отправляют сведения в службу для совместного использования со всеми текущими подписчиками.

В этом примере клиент и источник данных являются консольными программами (.exe файлами) и служба является библиотекой (.dll), размещенной в службах IIS. На рабочем столе отображаются действия клиента и источника данных.

Сервис использует дуплексное взаимодействие. ISampleContract Договор об оказании услуг связан с договором обратной ISampleClientCallback связи. Служба реализует операции подписки и отмены подписки, которые клиенты используют для присоединения или выхода из списка подписчиков. Служба также реализует операцию службы PublishPriceChange, которую вызывает программа источника данных, чтобы предоставить службу новой информацией. Клиентская программа реализует PriceChange операцию обслуживания, которая вызывается службой для уведомления всех подписчиков об изменении цены.

// 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);
}

Служба использует событие .NET Framework в качестве механизма для информирования всех подписчиков о новых сведениях. Когда клиент присоединяется к службе, вызывая метод Subscribe, он предоставляет обработчик событий. Когда клиент уходит, он отменяет подписку обработчика событий от события. Когда источник данных вызывает службу, чтобы сообщить об изменении цены, служба вызывает событие. Это вызывает каждый экземпляр службы, по одному для каждого клиента, который подписан, и приводит к выполнению обработчиков событий. Каждый обработчик событий передает сведения клиенту через функцию обратного вызова.

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);
        }

    }

При запуске примера запустите несколько клиентов. Клиенты подписываются на службу. Затем запустите программу источника данных, которая отправляет сведения в службу. Служба передает сведения всем подписчикам. Вы можете увидеть действия на каждой клиентской консоли, подтверждающие получение сведений. Нажмите клавишу ВВОД в окне клиента, чтобы завершить работу клиента.

Для настройки и сборки примера

  1. Убедитесь, что вы выполнили процедуру настройки One-Time для образцов Windows Communication Foundation.

  2. Чтобы создать версию решения на C# или Visual Basic .NET, следуйте инструкциям по сборке примеров Windows Communication Foundation .

Запуск примера на том же компьютере

  1. Проверьте, можно ли получить доступ к службе с помощью браузера, введя следующий адрес: http://localhost/servicemodelsamples/service.svc Страница подтверждения должна отображаться в ответ на действие.

  2. Запустите Client.exe из \client\bin\, из папки, предназначенной для конкретного языка. Действие клиента отображается в окне консоли клиента. Запустите несколько клиентов.

  3. Запустите Datasource.exe из \datasource\bin\, из подкаталога, соответствующего языку. Действие источника данных отображается в окне консоли. После того как источник данных отправит информацию в службу, она должна быть передана каждому клиенту.

  4. Если клиент, источник данных и программы службы не могут взаимодействовать, ознакомьтесь с советами по устранению неполадок для примеров WCF.

Запуск примера на разных компьютерах

  1. Настройте сервисную машину:

    1. На компьютере службы создайте виртуальный каталог с именем ServiceModelSamples. Пакетный файл Setupvroot.bat из процедуры установкиOne-Time для примеров Windows Communication Foundation можно использовать для создания каталога диска и виртуального каталога.

    2. Скопируйте файлы программы службы из %SystemDrive%\Inetpub\wwwroot\servicemodelsamples в виртуальный каталог ServiceModelSamples на компьютере службы. Не забудьте включить файлы в каталог \bin.

    3. Проверьте, можно ли получить доступ к службе с клиентского компьютера с помощью браузера.

  2. Настройте клиентские компьютеры:

    1. Скопируйте файлы клиентской программы из папки \client\bin\ в папку для конкретного языка на клиентские компьютеры.

    2. В каждом файле конфигурации клиента измените значение адреса определения конечной точки на соответствие новому адресу службы. Замените все ссылки на localhost полным доменным именем в адресе.

  3. Настройте компьютер источника данных:

    1. Скопируйте файлы программы источника данных из папки \datasource\bin\, находящейся в папке для конкретного языка, на машину источника данных.

    2. В файле конфигурации источника данных измените значение адреса определения конечной точки, чтобы он соответствовал новому адресу службы. Замените все ссылки на localhost полным доменным именем в адресе.

  4. На клиентских компьютерах запустите Client.exe из командной строки.

  5. На компьютере источника данных запустите Datasource.exe из командной строки.