Vorgehensweise: Implementieren eines SuchproxysHow to: Implement a Discovery Proxy

In diesem Thema wird erläutert, wie Sie einen Suchproxy implementieren.This topic explains how to implement a discovery proxy. Weitere Informationen zu den Discovery-Feature in Windows Communication Foundation (WCF), finden Sie unter Überblick über WCF-Ermittlung.For more information about the discovery feature in Windows Communication Foundation (WCF), see WCF Discovery Overview. Sie können einen Suchproxy implementieren, indem Sie eine Klasse erstellen, die die abstrakte DiscoveryProxy-Klasse erweitert.A discovery proxy can be implemented by creating a class that extends the DiscoveryProxy abstract class. Es gibt eine Reihe von anderen Unterstützungsklassen, die in diesem Beispiel definiert und verwendet werden.There are a number of other support classes defined and used in this sample. OnResolveAsyncResult, OnFindAsyncResult und AsyncResult.OnResolveAsyncResult, OnFindAsyncResult, and AsyncResult. Diese Klassen implementieren die IAsyncResult-Schnittstelle.These classes implement the IAsyncResult interface. Weitere Informationen zu IAsyncResult finden Sie unter System.IAsyncResult-Schnittstelle.For more information about IAsyncResult see System.IAsyncResult interface.

Das Implementieren eines Suchproxys ist in diesem Thema in drei Hauptteile aufgegliedert:Implementing a discovery proxy is broken down into three main parts in this topic:

  • Definieren einer Klasse, die einen Datenspeicher enthält und die abstrakte DiscoveryProxy-Klasse erweitertDefine a class that contains a data store and extends the abstract DiscoveryProxy class.

  • Implementieren der AsyncResult-HilfsklasseImplement the helper AsyncResult class.

  • Hosten des SuchproxysHost the Discovery Proxy.

So erstellen Sie ein neues KonsolenanwendungsprojektTo create a new console application project

  1. Starten Sie Visual Studio 2012Visual Studio 2012.Start Visual Studio 2012Visual Studio 2012.

  2. Erstellen Sie ein neues Konsolenanwendungsprojekt.Create a new console application project. Nennen Sie das Projekt DiscoveryProxy und die Projektmappe DiscoveryProxyExample.Name the project DiscoveryProxy and the name the solution DiscoveryProxyExample.

  3. Fügen Sie dem Projekt die folgenden Verweise hinzu.Add the following references to the project

    1. System.ServiceModel.dllSystem.ServiceModel.dll

    2. System.Servicemodel.Discovery.dllSystem.Servicemodel.Discovery.dll

    Achtung

    Stellen Sie sicher, dass Sie für diese Assemblys auf Version 4.0 oder höher verweisen.Ensure that you reference version 4.0 or greater of these assemblies.

So implementieren Sie die ProxyDiscoveryService-KlasseTo implement the ProxyDiscoveryService class

  1. Fügen Sie dem Projekt eine neue Codedatei hinzu, und geben Sie dieser den Namen DiscoveryProxy.cs.Add a new code file to your project and name it DiscoveryProxy.cs.

  2. Fügen Sie der Datei DiscoveryProxy.cs die folgenden using-Anweisungen hinzu.Add the following using statements to DiscoveryProxy.cs.

    using System;  
    using System.Collections.Generic;  
    using System.ServiceModel;  
    using System.ServiceModel.Discovery;  
    using System.Xml;  
    
  3. Leiten Sie DiscoveryProxyService von DiscoveryProxy ab.Derive the DiscoveryProxyService from DiscoveryProxy. Wenden Sie das ServiceBehavior-Attribut auf die Klasse an, wie im folgenden Beispiel gezeigt.Apply the ServiceBehavior attribute to the class as shown in the following example.

    // Implement DiscoveryProxy by extending the DiscoveryProxy class and overriding the abstract methods  
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]  
    public class DiscoveryProxyService : DiscoveryProxy  
    {  
    }  
    
  4. Definieren Sie in der DiscoveryProxy-Klasse ein Wörterbuch für die registrierten Dienste.Inside the DiscoveryProxy class define a dictionary to hold the registered services.

    // Repository to store EndpointDiscoveryMetadata.   
    Dictionary<EndpointAddress, EndpointDiscoveryMetadata> onlineServices;  
    
  5. Definieren Sie einen Konstruktor, der das Wörterbuch initialisiert.Define a constructor that initializes the dictionary.

    public DiscoveryProxyService()  
            {  
                this.onlineServices = new Dictionary<EndpointAddress, EndpointDiscoveryMetadata>();  
            }  
    

So definieren Sie die Methoden, die zum Aktualisieren des Suchproxycaches verwendet werdenTo define the methods used to update the discovery proxy cache

  1. Implementieren Sie die AddOnlineservice-Methode, um dem Cache Dienste hinzuzufügen.Implement the AddOnlineservice method to add services to the cache. Diese Methode wird jedes Mal aufgerufen, wenn der Proxy eine Ankündigungsmeldung empfängt.This is called every time the proxy receives an announcement message.

    void AddOnlineService(EndpointDiscoveryMetadata endpointDiscoveryMetadata)  
            {  
                lock (this.onlineServices)  
                {  
                    this.onlineServices[endpointDiscoveryMetadata.Address] = endpointDiscoveryMetadata;                  
                }  
    
                PrintDiscoveryMetadata(endpointDiscoveryMetadata, "Adding");  
            }  
    
  2. Implementieren Sie die RemoveOnlineService-Methode, die zum Entfernen von Diensten aus dem Cache verwendet wird.Implement the RemoveOnlineService method that is used to remove services from the cache.

    void RemoveOnlineService(EndpointDiscoveryMetadata endpointDiscoveryMetadata)  
            {  
                if (endpointDiscoveryMetadata != null)  
                {  
                    lock (this.onlineServices)  
                    {  
                        this.onlineServices.Remove(endpointDiscoveryMetadata.Address);                      
                    }  
    
                    PrintDiscoveryMetadata(endpointDiscoveryMetadata, "Removing");  
                }      
            }  
    
  3. Implementieren Sie die MatchFromOnlineService-Methoden, die einen Dienst mit einem Dienst im Wörterbuch vergleichen.Implement the MatchFromOnlineService methods that attempt to match a service with a service in the dictionary.

    void MatchFromOnlineService(FindRequestContext findRequestContext)  
            {  
                lock (this.onlineServices)  
                {  
                    foreach (EndpointDiscoveryMetadata endpointDiscoveryMetadata in this.onlineServices.Values)  
                    {  
                        if (findRequestContext.Criteria.IsMatch(endpointDiscoveryMetadata))  
                        {  
                            findRequestContext.AddMatchingEndpoint(endpointDiscoveryMetadata);  
                        }  
                    }  
                }  
            }  
    
    EndpointDiscoveryMetadata MatchFromOnlineService(ResolveCriteria criteria)  
            {  
                EndpointDiscoveryMetadata matchingEndpoint = null;  
                lock (this.onlineServices)  
                {  
                    foreach (EndpointDiscoveryMetadata endpointDiscoveryMetadata in this.onlineServices.Values)  
                    {  
                        if (criteria.Address == endpointDiscoveryMetadata.Address)  
                        {  
                            matchingEndpoint = endpointDiscoveryMetadata;  
                        }  
                    }  
                }  
                return matchingEndpoint;  
            }  
    
  4. Implementieren Sie die PrintDiscoveryMetadata-Methode, die für Benutzer eine Konsolentextausgabe zu den Aktivitäten des Suchproxys bereitstellt.Implement the PrintDiscoveryMetadata method that provides the user with console text output of what the discovery proxy is doing.

    void PrintDiscoveryMetadata(EndpointDiscoveryMetadata endpointDiscoveryMetadata, string verb)  
            {  
                Console.WriteLine("\n**** " + verb + " service of the following type from cache. ");  
                foreach (XmlQualifiedName contractName in endpointDiscoveryMetadata.ContractTypeNames)  
                {  
                    Console.WriteLine("** " + contractName.ToString());  
                    break;  
                }  
                Console.WriteLine("**** Operation Completed");  
            }  
    
  5. Fügen Sie der Datei DiscoveryProxyService die folgenden AsyncResult-Klassen hinzu.Add the following AsyncResult classes to the DiscoveryProxyService. Diese Klassen werden verwendet, um zwischen den einzelnen asynchronen Vorgangsergebnissen zu unterscheiden.These classes are used to differentiate between the different asynchronous operation results.

    sealed class OnOnlineAnnouncementAsyncResult : AsyncResult  
            {  
                public OnOnlineAnnouncementAsyncResult(AsyncCallback callback, object state)  
                    : base(callback, state)  
                {  
                    this.Complete(true);  
                }  
    
                public static void End(IAsyncResult result)  
                {  
                    AsyncResult.End<OnOnlineAnnouncementAsyncResult>(result);  
                }  
            }  
    
            sealed class OnOfflineAnnouncementAsyncResult : AsyncResult  
            {  
                public OnOfflineAnnouncementAsyncResult(AsyncCallback callback, object state)  
                    : base(callback, state)  
                {  
                    this.Complete(true);  
                }  
    
                public static void End(IAsyncResult result)  
                {  
                    AsyncResult.End<OnOfflineAnnouncementAsyncResult>(result);  
                }  
            }  
    
            sealed class OnFindAsyncResult : AsyncResult  
            {  
                public OnFindAsyncResult(AsyncCallback callback, object state)  
                    : base(callback, state)  
                {  
                    this.Complete(true);  
                }  
    
                public static void End(IAsyncResult result)  
                {  
                    AsyncResult.End<OnFindAsyncResult>(result);  
                }  
            }  
    
            sealed class OnResolveAsyncResult : AsyncResult  
            {  
                EndpointDiscoveryMetadata matchingEndpoint;  
    
                public OnResolveAsyncResult(EndpointDiscoveryMetadata matchingEndpoint, AsyncCallback callback, object state)  
                    : base(callback, state)  
                {  
                    this.matchingEndpoint = matchingEndpoint;  
                    this.Complete(true);  
                }  
    
                public static EndpointDiscoveryMetadata End(IAsyncResult result)  
                {  
                    OnResolveAsyncResult thisPtr = AsyncResult.End<OnResolveAsyncResult>(result);  
                    return thisPtr.matchingEndpoint;  
                }  
            }  
    

So definieren Sie die Methoden, die die Suchproxyfunktionalität implementierenTo define the methods that implement the discovery proxy functionality

  1. Überschreiben Sie die DiscoveryProxy.OnBeginOnlineAnnouncement-Methode.Override the DiscoveryProxy.OnBeginOnlineAnnouncement method. Diese Methode wird aufgerufen, wenn der Suchproxy eine Onlineankündigungsmeldung empfängt.This method is called when the discovery proxy receives an online announcement message.

    // OnBeginOnlineAnnouncement method is called when a Hello message is received by the Proxy  
            protected override IAsyncResult OnBeginOnlineAnnouncement(DiscoveryMessageSequence messageSequence, EndpointDiscoveryMetadata endpointDiscoveryMetadata, AsyncCallback callback, object state)  
            {          
                this.AddOnlineService(endpointDiscoveryMetadata);  
                return new OnOnlineAnnouncementAsyncResult(callback, state);  
            }  
    
  2. Überschreiben Sie die DiscoveryProxy.OnEndOnlineAnnouncement-Methode.Override the DiscoveryProxy.OnEndOnlineAnnouncement method. Diese Methode wird aufgerufen, wenn der Suchproxy die Verarbeitung einer Ankündigungsmeldung beendet.This method is called when the discovery proxy finishes processing an announcement message.

    protected override void OnEndOnlineAnnouncement(IAsyncResult result)  
            {  
                OnOnlineAnnouncementAsyncResult.End(result);  
            }  
    
  3. Überschreiben Sie die DiscoveryProxy.OnBeginOfflineAnnouncement-Methode.Override the DiscoveryProxy.OnBeginOfflineAnnouncement method. Diese Methode wird aufgerufen, wenn der Suchproxy eine Offlineankündigungsmeldung empfängt.This method is called with the discovery proxy receives an offline announcement message.

    // OnBeginOfflineAnnouncement method is called when a Bye message is received by the Proxy  
            protected override IAsyncResult OnBeginOfflineAnnouncement(DiscoveryMessageSequence messageSequence, EndpointDiscoveryMetadata endpointDiscoveryMetadata, AsyncCallback callback, object state)  
            {  
                this.RemoveOnlineService(endpointDiscoveryMetadata);  
                return new OnOfflineAnnouncementAsyncResult(callback, state);  
            }  
    
  4. Überschreiben Sie die DiscoveryProxy.OnEndOfflineAnnouncement-Methode.Override the DiscoveryProxy.OnEndOfflineAnnouncement method. Diese Methode wird aufgerufen, wenn der Suchproxy die Verarbeitung einer Offlineankündigungsmeldung beendet.This method is called when the discovery proxy finishes processing an offline announcement message.

    protected override void OnEndOfflineAnnouncement(IAsyncResult result)  
            {  
                OnOfflineAnnouncementAsyncResult.End(result);  
            }  
    
  5. Überschreiben Sie die DiscoveryProxy.OnBeginFind-Methode.Override the DiscoveryProxy.OnBeginFind method. Diese Methode wird aufgerufen, wenn der Suchproxy eine Suchanforderung empfängt.This method is called when the discovery proxy receives a find request.

    // OnBeginFind method is called when a Probe request message is received by the Proxy  
            protected override IAsyncResult OnBeginFind(FindRequestContext findRequestContext, AsyncCallback callback, object state)  
            {  
                this.MatchFromOnlineService(findRequestContext);  
                return new OnFindAsyncResult(callback, state);  
            }  
    protected override IAsyncResult OnBeginFind(FindRequest findRequest, AsyncCallback callback, object state)  
    {  
        Collection<EndpointDiscoveryMetadata> matchingEndpoints = MatchFromCache(findRequest.Criteria);  
        return new OnFindAsyncResult(  
                    matchingEndpoints,  
                    callback,  
                    state);  
    }  
    
  6. Überschreiben Sie die DiscoveryProxy.OnEndFind-Methode.Override the DiscoveryProxy.OnEndFind method. Diese Methode wird aufgerufen, wenn der Suchproxy die Verarbeitung einer Suchanforderung beendet.This method is called when the discovery proxy finishes processing a find request.

    protected override void OnEndFind(IAsyncResult result)  
            {  
                OnFindAsyncResult.End(result);  
            }  
    
  7. Überschreiben Sie die DiscoveryProxy.OnBeginResolve-Methode.Override the DiscoveryProxy.OnBeginResolve method. Diese Methode wird aufgerufen, wenn der Suchproxy eine Auflösungsnachricht empfängt.This method is called when the discovery proxy receives a resolve message.

    // OnBeginFind method is called when a Resolve request message is received by the Proxy  
            protected override IAsyncResult OnBeginResolve(ResolveCriteria resolveCriteria, AsyncCallback callback, object state)  
            {  
                return new OnResolveAsyncResult(this.MatchFromOnlineService(resolveCriteria), callback, state);  
            }  
    protected override IAsyncResult OnBeginResolve(ResolveRequest resolveRequest, AsyncCallback callback, object state)  
    {  
        return new OnResolveAsyncResult(  
            this.proxy.MatchFromOnlineService(resolveRequest.Criteria),  
            callback,  
            state);  
    }  
    
  8. Überschreiben Sie die DiscoveryProxy.OnEndResolve-Methode.Override the DiscoveryProxy.OnEndResolve method. Diese Methode wird aufgerufen, wenn der Suchproxy die Verarbeitung einer Auflösungsnachricht beendet.This method is called when the discovery proxy finishes processing a resolve message.

    protected override EndpointDiscoveryMetadata OnEndResolve(IAsyncResult result)  
    {  
        return OnResolveAsyncResult.End(result);  
    }  
    

Die OnBegin/The OnBegin.. / OnEnd./ OnEnd.. -Methoden stellen die Logik für die nachfolgenden Suchvorgänge bereit.methods provide the logic for the subsequent discovery operations. Die Methoden OnBeginFind und OnEndFind implementieren z. B. die Suchlogik für den Suchproxy.For example the OnBeginFind and OnEndFind methods implement the find logic for discovery proxy. Wenn der Suchproxy eine Überprüfungsmeldung empfängt, werden diese Methoden ausgeführt, um eine Antwort an den Client zurückzusenden.When the discovery proxy receives a probe message these methods are executed to send a response back to the client. Sie können die Suchlogik nach Belieben ändern. Beispielsweise können Sie als Teil des Suchvorgangs eine benutzerdefinierte Bereichsübereinstimmung integrieren, die auf Algorithmen oder einer anwendungsspezifischen Analyse der XML-Metadaten basiert.You may modify the find logic as you wish, for example you can incorporate custom scope matching by algorithms or application specific XML metadata parsing as part of your find operation.

So implementieren Sie die AsyncResult-KlasseTo implement the AsyncResult class

  1. Definieren Sie die abstrakte Basisklasse AsyncResult, die zum Ableiten der verschiedenen AsyncResult-Klassen verwendet wird.Define the abstract base class AsyncResult which is used to derive the various async result classes.

  2. Erstellen Sie eine neue Codedatei mit dem Namen AsyncResult.cs.Create a new code file called AsyncResult.cs.

  3. Fügen Sie der Datei AsyncResult.cs die folgenden using-Anweisungen hinzu.Add the following using statements to AsyncResult.cs.

    using System;  
    using System.Threading;  
    
  4. Fügen Sie die folgende AsyncResult-Klasse hinzu.Add the following AsyncResult class.

    abstract class AsyncResult : IAsyncResult  
        {  
            AsyncCallback callback;  
            bool completedSynchronously;  
            bool endCalled;  
            Exception exception;  
            bool isCompleted;  
            ManualResetEvent manualResetEvent;  
            object state;  
            object thisLock;  
    
            protected AsyncResult(AsyncCallback callback, object state)  
            {  
                this.callback = callback;  
                this.state = state;  
                this.thisLock = new object();  
            }  
    
            public object AsyncState  
            {  
                get  
                {  
                    return state;  
                }  
            }  
    
            public WaitHandle AsyncWaitHandle  
            {  
                get  
                {  
                    if (manualResetEvent != null)  
                    {  
                        return manualResetEvent;  
                    }  
                    lock (ThisLock)  
                    {  
                        if (manualResetEvent == null)  
                        {  
                            manualResetEvent = new ManualResetEvent(isCompleted);  
                        }  
                    }  
                    return manualResetEvent;  
                }  
            }  
    
            public bool CompletedSynchronously  
            {  
                get  
                {  
                    return completedSynchronously;  
                }  
            }  
    
            public bool IsCompleted  
            {  
                get  
                {  
                    return isCompleted;  
                }  
            }  
    
            object ThisLock  
            {  
                get  
                {  
                    return this.thisLock;  
                }  
            }  
    
            protected static TAsyncResult End<TAsyncResult>(IAsyncResult result)  
                where TAsyncResult : AsyncResult  
            {  
                if (result == null)  
                {  
                    throw new ArgumentNullException("result");  
                }  
    
                TAsyncResult asyncResult = result as TAsyncResult;  
    
                if (asyncResult == null)  
                {  
                    throw new ArgumentException("Invalid async result.", "result");  
                }  
    
                if (asyncResult.endCalled)  
                {  
                    throw new InvalidOperationException("Async object already ended.");  
                }  
    
                asyncResult.endCalled = true;  
    
                if (!asyncResult.isCompleted)  
                {  
                    asyncResult.AsyncWaitHandle.WaitOne();  
                }  
    
                if (asyncResult.manualResetEvent != null)  
                {  
                    asyncResult.manualResetEvent.Close();  
                }  
    
                if (asyncResult.exception != null)  
                {  
                    throw asyncResult.exception;  
                }  
    
                return asyncResult;  
            }  
    
            protected void Complete(bool completedSynchronously)  
            {  
                if (isCompleted)  
                {  
                    throw new InvalidOperationException("This async result is already completed.");  
                }  
    
                this.completedSynchronously = completedSynchronously;  
    
                if (completedSynchronously)  
                {  
                    this.isCompleted = true;  
                }  
                else  
                {  
                    lock (ThisLock)  
                    {  
                        this.isCompleted = true;  
                        if (this.manualResetEvent != null)  
                        {  
                            this.manualResetEvent.Set();  
                        }  
                    }  
                }  
    
                if (callback != null)  
                {  
                    callback(this);  
                }  
            }  
    
            protected void Complete(bool completedSynchronously, Exception exception)  
            {  
                this.exception = exception;  
                Complete(completedSynchronously);  
            }  
        }  
    

So hosten Sie den DiscoveryProxyTo host the DiscoveryProxy

  1. Öffnen Sie die Datei Program.cs im Projekt DiscoveryProxyExample.Open the Program.cs file in the DiscoveryProxyExample project.

  2. Fügen Sie die folgenden using-Anweisungen hinzu.Add the following using statements.

    using System;  
    using System.ServiceModel;  
    using System.ServiceModel.Discovery;  
    
  3. Fügen Sie in der Main()-Methode den folgenden Code hinzu.Within the Main() method, add the following code. Dadurch wird eine Instanz der DiscoveryProxy-Klasse erstellt.This creates an instance of the DiscoveryProxy class.

    Uri probeEndpointAddress = new Uri("net.tcp://localhost:8001/Probe");  
                Uri announcementEndpointAddress = new Uri("net.tcp://localhost:9021/Announcement");  
    
                // Host the DiscoveryProxy service  
                ServiceHost proxyServiceHost = new ServiceHost(new DiscoveryProxyService());  
    
  4. Fügen Sie danach den folgenden Code hinzu, um einen Suchendpunkt und einen Ankündigungsendpunkt hinzuzufügen.Next add the following code to add a discovery endpoint and an announcement endpoint.

    try  
              {                  
                  // Add DiscoveryEndpoint to receive Probe and Resolve messages  
                  DiscoveryEndpoint discoveryEndpoint = new DiscoveryEndpoint(new NetTcpBinding(), new EndpointAddress(probeEndpointAddress));  
                  discoveryEndpoint.IsSystemEndpoint = false;  
    
                  // Add AnnouncementEndpoint to receive Hello and Bye announcement messages  
                  AnnouncementEndpoint announcementEndpoint = new AnnouncementEndpoint(new NetTcpBinding(), new EndpointAddress(announcementEndpointAddress));                  
    
                  proxyServiceHost.AddServiceEndpoint(discoveryEndpoint);  
                  proxyServiceHost.AddServiceEndpoint(announcementEndpoint);  
    
                  proxyServiceHost.Open();  
    
                  Console.WriteLine("Proxy Service started.");  
                  Console.WriteLine();  
                  Console.WriteLine("Press <ENTER> to terminate the service.");  
                  Console.WriteLine();  
                  Console.ReadLine();  
    
                  proxyServiceHost.Close();  
              }  
              catch (CommunicationException e)  
              {  
                  Console.WriteLine(e.Message);  
              }  
              catch (TimeoutException e)  
              {  
                  Console.WriteLine(e.Message);  
              }     
    
              if (proxyServiceHost.State != CommunicationState.Closed)  
              {  
                  Console.WriteLine("Aborting the service...");  
                  proxyServiceHost.Abort();  
              }  
    

Sie haben die Implementierung des Suchproxys abgeschlossen.You have completed implementing the discovery proxy. Fortfahren mit Vorgehensweise: Implementieren eines ermittelbaren Diensts, der beim Suchproxy registriert.Continue on to How to: Implement a Discoverable Service that Registers with the Discovery Proxy.

BeispielExample

Dies ist die vollständige Codeauflistung für dieses Thema.This is the full listing of the code used in this topic.

// DiscoveryProxy.cs  
//----------------------------------------------------------------  
// Copyright (c) Microsoft Corporation.  All rights reserved.  
//----------------------------------------------------------------  

using System;  
using System.Collections.Generic;  
using System.ServiceModel;  
using System.ServiceModel.Discovery;  
using System.Xml;  

namespace Microsoft.Samples.Discovery  
{  
    // Implement DiscoveryProxy by extending the DiscoveryProxy class and overriding the abstract methods  
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]  
    public class DiscoveryProxyService : DiscoveryProxy  
    {  
        // Repository to store EndpointDiscoveryMetadata. A database or a flat file could also be used instead.  
        Dictionary<EndpointAddress, EndpointDiscoveryMetadata> onlineServices;  

        public DiscoveryProxyService()  
        {  
            this.onlineServices = new Dictionary<EndpointAddress, EndpointDiscoveryMetadata>();  
        }  

        // OnBeginOnlineAnnouncement method is called when a Hello message is received by the Proxy  
        protected override IAsyncResult OnBeginOnlineAnnouncement(DiscoveryMessageSequence messageSequence, EndpointDiscoveryMetadata endpointDiscoveryMetadata, AsyncCallback callback, object state)  
        {          
            this.AddOnlineService(endpointDiscoveryMetadata);  
            return new OnOnlineAnnouncementAsyncResult(callback, state);  
        }  

        protected override void OnEndOnlineAnnouncement(IAsyncResult result)  
        {  
            OnOnlineAnnouncementAsyncResult.End(result);  
        }  

        // OnBeginOfflineAnnouncement method is called when a Bye message is received by the Proxy  
        protected override IAsyncResult OnBeginOfflineAnnouncement(DiscoveryMessageSequence messageSequence, EndpointDiscoveryMetadata endpointDiscoveryMetadata, AsyncCallback callback, object state)  
        {  
            this.RemoveOnlineService(endpointDiscoveryMetadata);  
            return new OnOfflineAnnouncementAsyncResult(callback, state);  
        }  

        protected override void OnEndOfflineAnnouncement(IAsyncResult result)  
        {  
            OnOfflineAnnouncementAsyncResult.End(result);  
        }  

        // OnBeginFind method is called when a Probe request message is received by the Proxy  
        protected override IAsyncResult OnBeginFind(FindRequestContext findRequestContext, AsyncCallback callback, object state)  
        {  
            this.MatchFromOnlineService(findRequestContext);  
            return new OnFindAsyncResult(callback, state);  
        }  

        protected override void OnEndFind(IAsyncResult result)  
        {  
            OnFindAsyncResult.End(result);  
        }  

        // OnBeginFind method is called when a Resolve request message is received by the Proxy  
        protected override IAsyncResult OnBeginResolve(ResolveCriteria resolveCriteria, AsyncCallback callback, object state)  
        {  
            return new OnResolveAsyncResult(this.MatchFromOnlineService(resolveCriteria), callback, state);  
        }  

        protected override EndpointDiscoveryMetadata OnEndResolve(IAsyncResult result)  
        {  
            return OnResolveAsyncResult.End(result);  
        }  

        // The following are helper methods required by the Proxy implementation  
        void AddOnlineService(EndpointDiscoveryMetadata endpointDiscoveryMetadata)  
        {  
            lock (this.onlineServices)  
            {  
                this.onlineServices[endpointDiscoveryMetadata.Address] = endpointDiscoveryMetadata;                  
            }  

            PrintDiscoveryMetadata(endpointDiscoveryMetadata, "Adding");  
        }  

        void RemoveOnlineService(EndpointDiscoveryMetadata endpointDiscoveryMetadata)  
        {  
            if (endpointDiscoveryMetadata != null)  
            {  
                lock (this.onlineServices)  
                {  
                    this.onlineServices.Remove(endpointDiscoveryMetadata.Address);                      
                }  

                PrintDiscoveryMetadata(endpointDiscoveryMetadata, "Removing");  
            }      
        }  

        void MatchFromOnlineService(FindRequestContext findRequestContext)  
        {  
            lock (this.onlineServices)  
            {  
                foreach (EndpointDiscoveryMetadata endpointDiscoveryMetadata in this.onlineServices.Values)  
                {  
                    if (findRequestContext.Criteria.IsMatch(endpointDiscoveryMetadata))  
                    {  
                        findRequestContext.AddMatchingEndpoint(endpointDiscoveryMetadata);  
                    }  
                }  
            }  
        }  

        EndpointDiscoveryMetadata MatchFromOnlineService(ResolveCriteria criteria)  
        {  
            EndpointDiscoveryMetadata matchingEndpoint = null;  
            lock (this.onlineServices)  
            {  
                foreach (EndpointDiscoveryMetadata endpointDiscoveryMetadata in this.onlineServices.Values)  
                {  
                    if (criteria.Address == endpointDiscoveryMetadata.Address)  
                    {  
                        matchingEndpoint = endpointDiscoveryMetadata;  
                    }  
                }  
            }  
            return matchingEndpoint;  
        }  

        void PrintDiscoveryMetadata(EndpointDiscoveryMetadata endpointDiscoveryMetadata, string verb)  
        {  
            Console.WriteLine("\n**** " + verb + " service of the following type from cache. ");  
            foreach (XmlQualifiedName contractName in endpointDiscoveryMetadata.ContractTypeNames)  
            {  
                Console.WriteLine("** " + contractName.ToString());  
                break;  
            }  
            Console.WriteLine("**** Operation Completed");  
        }  

        sealed class OnOnlineAnnouncementAsyncResult : AsyncResult  
        {  
            public OnOnlineAnnouncementAsyncResult(AsyncCallback callback, object state)  
                : base(callback, state)  
            {  
                this.Complete(true);  
            }  

            public static void End(IAsyncResult result)  
            {  
                AsyncResult.End<OnOnlineAnnouncementAsyncResult>(result);  
            }  
        }  

        sealed class OnOfflineAnnouncementAsyncResult : AsyncResult  
        {  
            public OnOfflineAnnouncementAsyncResult(AsyncCallback callback, object state)  
                : base(callback, state)  
            {  
                this.Complete(true);  
            }  

            public static void End(IAsyncResult result)  
            {  
                AsyncResult.End<OnOfflineAnnouncementAsyncResult>(result);  
            }  
        }  

        sealed class OnFindAsyncResult : AsyncResult  
        {  
            public OnFindAsyncResult(AsyncCallback callback, object state)  
                : base(callback, state)  
            {  
                this.Complete(true);  
            }  

            public static void End(IAsyncResult result)  
            {  
                AsyncResult.End<OnFindAsyncResult>(result);  
            }  
        }  

        sealed class OnResolveAsyncResult : AsyncResult  
        {  
            EndpointDiscoveryMetadata matchingEndpoint;  

            public OnResolveAsyncResult(EndpointDiscoveryMetadata matchingEndpoint, AsyncCallback callback, object state)  
                : base(callback, state)  
            {  
                this.matchingEndpoint = matchingEndpoint;  
                this.Complete(true);  
            }  

            public static EndpointDiscoveryMetadata End(IAsyncResult result)  
            {  
                OnResolveAsyncResult thisPtr = AsyncResult.End<OnResolveAsyncResult>(result);  
                return thisPtr.matchingEndpoint;  
            }  
        }  
    }  
}  
// AsyncResult.cs  
//----------------------------------------------------------------  
// Copyright (c) Microsoft Corporation.  All rights reserved.  
//----------------------------------------------------------------  

using System;  
using System.Threading;  

namespace Microsoft.Samples.Discovery  
{  
    abstract class AsyncResult : IAsyncResult  
    {  
        AsyncCallback callback;  
        bool completedSynchronously;  
        bool endCalled;  
        Exception exception;  
        bool isCompleted;  
        ManualResetEvent manualResetEvent;  
        object state;  
        object thisLock;  

        protected AsyncResult(AsyncCallback callback, object state)  
        {  
            this.callback = callback;  
            this.state = state;  
            this.thisLock = new object();  
        }  

        public object AsyncState  
        {  
            get  
            {  
                return state;  
            }  
        }  

        public WaitHandle AsyncWaitHandle  
        {  
            get  
            {  
                if (manualResetEvent != null)  
                {  
                    return manualResetEvent;  
                }  
                lock (ThisLock)  
                {  
                    if (manualResetEvent == null)  
                    {  
                        manualResetEvent = new ManualResetEvent(isCompleted);  
                    }  
                }  
                return manualResetEvent;  
            }  
        }  

        public bool CompletedSynchronously  
        {  
            get  
            {  
                return completedSynchronously;  
            }  
        }  

        public bool IsCompleted  
        {  
            get  
            {  
                return isCompleted;  
            }  
        }  

        object ThisLock  
        {  
            get  
            {  
                return this.thisLock;  
            }  
        }  

        protected static TAsyncResult End<TAsyncResult>(IAsyncResult result)  
            where TAsyncResult : AsyncResult  
        {  
            if (result == null)  
            {  
                throw new ArgumentNullException("result");  
            }  

            TAsyncResult asyncResult = result as TAsyncResult;  

            if (asyncResult == null)  
            {  
                throw new ArgumentException("Invalid async result.", "result");  
            }  

            if (asyncResult.endCalled)  
            {  
                throw new InvalidOperationException("Async object already ended.");  
            }  

            asyncResult.endCalled = true;  

            if (!asyncResult.isCompleted)  
            {  
                asyncResult.AsyncWaitHandle.WaitOne();  
            }  

            if (asyncResult.manualResetEvent != null)  
            {  
                asyncResult.manualResetEvent.Close();  
            }  

            if (asyncResult.exception != null)  
            {  
                throw asyncResult.exception;  
            }  

            return asyncResult;  
        }  

        protected void Complete(bool completedSynchronously)  
        {  
            if (isCompleted)  
            {  
                throw new InvalidOperationException("This async result is already completed.");  
            }  

            this.completedSynchronously = completedSynchronously;  

            if (completedSynchronously)  
            {  
                this.isCompleted = true;  
            }  
            else  
            {  
                lock (ThisLock)  
                {  
                    this.isCompleted = true;  
                    if (this.manualResetEvent != null)  
                    {  
                        this.manualResetEvent.Set();  
                    }  
                }  
            }  

            if (callback != null)  
            {  
                callback(this);  
            }  
        }  

        protected void Complete(bool completedSynchronously, Exception exception)  
        {  
            this.exception = exception;  
            Complete(completedSynchronously);  
        }  
    }  
}  
// program.cs  
//----------------------------------------------------------------  
// Copyright (c) Microsoft Corporation.  All rights reserved.  
//----------------------------------------------------------------  

using System;  
using System.ServiceModel;  
using System.ServiceModel.Discovery;  

namespace Microsoft.Samples.Discovery  
{  
    class Program  
    {  
        public static void Main()  
        {  
            Uri probeEndpointAddress = new Uri("net.tcp://localhost:8001/Probe");  
            Uri announcementEndpointAddress = new Uri("net.tcp://localhost:9021/Announcement");  

            // Host the DiscoveryProxy service  
            ServiceHost proxyServiceHost = new ServiceHost(new DiscoveryProxyService());  

            try  
            {                  
                // Add DiscoveryEndpoint to receive Probe and Resolve messages  
                DiscoveryEndpoint discoveryEndpoint = new DiscoveryEndpoint(new NetTcpBinding(), new EndpointAddress(probeEndpointAddress));  
                discoveryEndpoint.IsSystemEndpoint = false;  

                // Add AnnouncementEndpoint to receive Hello and Bye announcement messages  
                AnnouncementEndpoint announcementEndpoint = new AnnouncementEndpoint(new NetTcpBinding(), new EndpointAddress(announcementEndpointAddress));                  

                proxyServiceHost.AddServiceEndpoint(discoveryEndpoint);  
                proxyServiceHost.AddServiceEndpoint(announcementEndpoint);  

                proxyServiceHost.Open();  

                Console.WriteLine("Proxy Service started.");  
                Console.WriteLine();  
                Console.WriteLine("Press <ENTER> to terminate the service.");  
                Console.WriteLine();  
                Console.ReadLine();  

                proxyServiceHost.Close();  
            }  
            catch (CommunicationException e)  
            {  
                Console.WriteLine(e.Message);  
            }  
            catch (TimeoutException e)  
            {  
                Console.WriteLine(e.Message);  
            }     

            if (proxyServiceHost.State != CommunicationState.Closed)  
            {  
                Console.WriteLine("Aborting the service...");  
                proxyServiceHost.Abort();  
            }  
        }  
    }  
}  

Siehe auchSee Also

Übersicht über die WCF-SucheWCF Discovery Overview
Vorgehensweise: Implementieren eines ermittelbaren Diensts, der beim Suchproxy registriert istHow to: Implement a Discoverable Service that Registers with the Discovery Proxy
Vorgehensweise: Implementieren einer Clientanwendung, die den Suchproxy zum Suchen nach einem Dienst verwendetHow to: Implement a Client Application that Uses the Discovery Proxy to Find a Service
Vorgehensweise: Testen des SuchproxysHow to: Test the Discovery Proxy