Wzorce projektowe: publikowanie/subskrybowanie oparte na liście
Przykład ListBasedPublishSubscribe ilustruje wzorzec publikowania i subskrybowania oparty na liście zaimplementowany jako program Windows Communication Foundation (WCF).
Uwaga
Procedura instalacji i instrukcje kompilacji dla tego przykładu znajdują się na końcu tego tematu.
Wzorzec projektu Publish-Subscribe oparty na liście został opisany w publikacji Microsoft Patterns & Practices (Wzorce i praktyki firmy Microsoft), Integration Patterns (Wzorce integracji). Wzorzec Publish-Subscribe przekazuje informacje do kolekcji adresatów, którzy zasubskrybowali temat informacyjny. Subskrypcja publikowania opartego na liście utrzymuje listę subskrybentów. Jeśli istnieją informacje do udostępnienia, kopia jest wysyłana do każdego subskrybenta na liście. W tym przykładzie pokazano dynamiczny wzorzec publikowania-subskrybowania oparty na liście, w którym klienci mogą subskrybować lub anulować subskrypcję tak często, jak to wymagane.
Przykład Publikowania-subskrybowania opartego na liście składa się z klienta, usługi i programu źródła danych. Może istnieć więcej niż jeden klient i więcej niż jeden program źródła danych. Klienci subskrybują usługę, otrzymują powiadomienia i anulują subskrypcję. Programy źródła danych wysyłają informacje do usługi, które mają być udostępniane wszystkim bieżącym subskrybentom.
W tym przykładzie klient i źródło danych to programy konsolowe (pliki .exe), a usługa jest biblioteką (.dll) hostowaną w usługach Internet Information Services (IIS). Działanie klienta i źródła danych jest widoczne na pulpicie.
Usługa korzysta z komunikacji dwukierunkowej. ISampleContract
Kontrakt usługi jest sparowany z kontraktem wywołania zwrotnegoISampleClientCallback
. Usługa implementuje operacje subskrybowania i anulowania subskrypcji usługi, których klienci używają do dołączania lub opuszczania listy subskrybentów. Usługa implementuje również operację PublishPriceChange
usługi, którą program źródła danych wywołuje w celu udostępnienia usłudze nowych informacji. Program kliencki implementuje operację PriceChange
usługi, którą usługa wywołuje, aby powiadomić wszystkich subskrybentów o zmianie ceny.
// 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);
}
Usługa używa zdarzenia .NET Framework jako mechanizmu informowania wszystkich subskrybentów o nowych informacjach. Gdy klient dołącza do usługi, wywołując usługę Subskrybuj, udostępnia procedurę obsługi zdarzeń. Po opuszczeniu klienta program obsługi zdarzeń anuluje subskrypcję programu obsługi zdarzeń. Gdy źródło danych wywołuje usługę, aby zgłosić zmianę ceny, usługa zgłasza zdarzenie. Spowoduje to wywołanie każdego wystąpienia usługi, po jednym dla każdego klienta, który zasubskrybował, i powoduje wykonanie ich procedur obsługi zdarzeń. Każda procedura obsługi zdarzeń przekazuje informacje do klienta za pośrednictwem funkcji wywołania zwrotnego.
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);
}
}
Po uruchomieniu przykładu uruchom kilku klientów. Klienci subskrybują usługę. Następnie uruchom program źródła danych, który wysyła informacje do usługi. Usługa przekazuje informacje wszystkim subskrybentom. W każdej konsoli klienta można zobaczyć działanie potwierdzające, że informacje zostały odebrane. Naciśnij klawisz ENTER w oknie klienta, aby zamknąć klienta.
Aby skonfigurować i skompilować przykład
Upewnij się, że wykonano procedurę instalacji jednorazowej dla przykładów programu Windows Communication Foundation.
Aby skompilować wersję rozwiązania w języku C# lub Visual Basic .NET, postępuj zgodnie z instrukcjami w temacie Building the Windows Communication Foundation Samples (Tworzenie przykładów programu Windows Communication Foundation).
Aby uruchomić przykład na tej samej maszynie
Przetestuj, czy możesz uzyskać dostęp do usługi przy użyciu przeglądarki, wprowadzając następujący adres:
http://localhost/servicemodelsamples/service.svc
. W odpowiedzi powinna zostać wyświetlona strona potwierdzenia.Uruchom Client.exe z folderu \client\bin\, z folderu specyficznego dla języka. Działanie klienta jest wyświetlane w oknie konsoli klienta. Uruchom kilku klientów.
Uruchom Datasource.exe z folderu \datasource\bin\, z folderu specyficznego dla języka. Działanie źródła danych jest wyświetlane w oknie konsoli. Gdy źródło danych wysyła informacje do usługi, powinno zostać przekazane do każdego klienta.
Jeśli klient, źródło danych i programy usług nie mogą się komunikować, zobacz Rozwiązywanie problemów Wskazówki dla przykładów programu WCF.
Aby uruchomić przykład między maszynami
Konfigurowanie maszyny usługi:
Na maszynie usługi utwórz katalog wirtualny o nazwie ServiceModelSamples. Plik wsadowy Setupvroot.bat z procedury instalacji jednorazowej dla przykładów programu Windows Communication Foundation można użyć do utworzenia katalogu dysku i katalogu wirtualnego.
Skopiuj pliki programu usługi z folderu %SystemDrive%\Inetpub\wwwroot\servicemodelsamples do katalogu wirtualnego ServiceModelSamples na maszynie usługi. Pamiętaj, aby uwzględnić pliki w katalogu \bin.
Przetestuj, czy możesz uzyskać dostęp do usługi z komputera klienckiego przy użyciu przeglądarki.
Skonfiguruj maszyny klienckie:
Skopiuj pliki programu klienckiego z folderu \client\bin\ w folderze specyficznym dla języka do komputerów klienckich.
W każdym pliku konfiguracji klienta zmień wartość adresu definicji punktu końcowego, aby odpowiadała nowemu adresowi usługi. Zastąp wszystkie odwołania do "localhost" w pełni kwalifikowaną nazwą domeny w adresie.
Konfigurowanie maszyny źródła danych:
Skopiuj pliki programu źródła danych z folderu \datasource\bin\ w folderze specyficznym dla języka do maszyny źródła danych.
W pliku konfiguracji źródła danych zmień wartość adresu definicji punktu końcowego, aby odpowiadała nowemu adresowi usługi. Zastąp wszystkie odwołania do "localhost" w pełni kwalifikowaną nazwą domeny w adresie.
Na maszynach klienckich uruchom Client.exe z wiersza polecenia.
Na maszynie źródła danych uruchom Datasource.exe z wiersza polecenia.