Procedura: implementare un proxy di individuazioneHow to: Implement a Discovery Proxy

In questo argomento viene illustrato come implementare un proxy di individuazione.This topic explains how to implement a discovery proxy. Per ulteriori informazioni sulle funzionalità di individuazione in Windows Communication Foundation (WCF), vedere Panoramica di WCF Discovery.For more information about the discovery feature in Windows Communication Foundation (WCF), see WCF Discovery Overview. È possibile implementare un proxy di individuazione creando una classe che estende la classe astratta DiscoveryProxy.A discovery proxy can be implemented by creating a class that extends the DiscoveryProxy abstract class. In questo esempio vengono definite e utilizzate altre classi di supporto.There are a number of other support classes defined and used in this sample. OnResolveAsyncResult, OnFindAsyncResult e AsyncResult.OnResolveAsyncResult, OnFindAsyncResult, and AsyncResult. Queste classi implementano l'interfaccia IAsyncResult.These classes implement the IAsyncResult interface. Per ulteriori informazioni IAsyncResult vedere interfaccia IAsyncResult.For more information about IAsyncResult see System.IAsyncResult interface.

In questo argomento l'implementazione di un proxy di individuazione è articolata in tre fasi principali:Implementing a discovery proxy is broken down into three main parts in this topic:

  • Definire una classe che contiene un archivio dati ed estende la classe astratta DiscoveryProxy.Define a class that contains a data store and extends the abstract DiscoveryProxy class.

  • Implementare la classe di supporto AsyncResult.Implement the helper AsyncResult class.

  • Ospitare il proxy di individuazione.Host the Discovery Proxy.

Per creare un nuovo progetto di applicazione consoleTo create a new console application project

  1. Avviare Visual Studio 2012Visual Studio 2012.Start Visual Studio 2012Visual Studio 2012.

  2. Creare un nuovo progetto applicazione console.Create a new console application project. Assegnare al progetto il nome DiscoveryProxy e assegnare alla soluzione il nome DiscoveryProxyExample.Name the project DiscoveryProxy and the name the solution DiscoveryProxyExample.

  3. Aggiungere al progetto i riferimenti seguentiAdd the following references to the project

    1. System.ServiceModel.dllSystem.ServiceModel.dll

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

    Attenzione

    Accertarsi di fare riferimento alla versione 4.0 o successiva di questi assembly.Ensure that you reference version 4.0 or greater of these assemblies.

Per implementare la classe ProxyDiscoveryServiceTo implement the ProxyDiscoveryService class

  1. Aggiungere un nuovo file di codice al progetto e denominarlo DiscoveryProxy.cs.Add a new code file to your project and name it DiscoveryProxy.cs.

  2. Aggiungere le istruzioni using seguenti a DiscoveryProxy.cs.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. Derivare DiscoveryProxyService da DiscoveryProxy.Derive the DiscoveryProxyService from DiscoveryProxy. Applicare l'attributo ServiceBehavior alla classe, come illustrato nell'esempio riportato di seguito.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. Nella classe DiscoveryProxy definire un dizionario per conservare i servizi registrati.Inside the DiscoveryProxy class define a dictionary to hold the registered services.

    // Repository to store EndpointDiscoveryMetadata.   
    Dictionary<EndpointAddress, EndpointDiscoveryMetadata> onlineServices;  
    
  5. Definire un costruttore che inizializza il dizionario.Define a constructor that initializes the dictionary.

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

Per definire i metodi utilizzati per aggiornare la cache del proxy di individuazioneTo define the methods used to update the discovery proxy cache

  1. Implementare il metodo AddOnlineservice per aggiungere servizi alla cache.Implement the AddOnlineservice method to add services to the cache. Questo metodo viene chiamato ogni volta che il proxy riceve un messaggio di annuncio.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. Implementare il metodo RemoveOnlineService utilizzato per rimuovere servizi dalla cache.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. Implementare i metodi MatchFromOnlineService, che tentano di individuare una corrispondenza tra un servizio e un servizio nel dizionario.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. Implementare il metodo PrintDiscoveryMetadata, che fornisce all'utente l'output di testo della console indicante le operazioni eseguite dal proxy di individuazione.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. Aggiungere le classi AsyncResult seguenti a DiscoveryProxyService.Add the following AsyncResult classes to the DiscoveryProxyService. Tali classi vengono utilizzate per distinguere i diversi risultati delle operazioni asincrone.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;  
                }  
            }  
    

Per definire i metodi che implementano la funzionalità del proxy di individuazioneTo define the methods that implement the discovery proxy functionality

  1. Eseguire l'override del metodo DiscoveryProxy.OnBeginOnlineAnnouncement.Override the DiscoveryProxy.OnBeginOnlineAnnouncement method. Questo metodo viene chiamato quando il proxy di individuazione riceve un messaggio di annuncio online.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. Eseguire l'override del metodo DiscoveryProxy.OnEndOnlineAnnouncement.Override the DiscoveryProxy.OnEndOnlineAnnouncement method. Questo metodo viene chiamato quando il proxy di individuazione completa l'elaborazione di un messaggio di annuncio.This method is called when the discovery proxy finishes processing an announcement message.

    protected override void OnEndOnlineAnnouncement(IAsyncResult result)  
            {  
                OnOnlineAnnouncementAsyncResult.End(result);  
            }  
    
  3. Eseguire l'override del metodo DiscoveryProxy.OnBeginOfflineAnnouncement.Override the DiscoveryProxy.OnBeginOfflineAnnouncement method. Questo metodo viene chiamato quando il proxy di individuazione riceve un messaggio di annuncio offline.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. Eseguire l'override del metodo DiscoveryProxy.OnEndOfflineAnnouncement.Override the DiscoveryProxy.OnEndOfflineAnnouncement method. Questo metodo viene chiamato quando il proxy di individuazione completa l'elaborazione di un messaggio di annuncio offline.This method is called when the discovery proxy finishes processing an offline announcement message.

    protected override void OnEndOfflineAnnouncement(IAsyncResult result)  
            {  
                OnOfflineAnnouncementAsyncResult.End(result);  
            }  
    
  5. Eseguire l'override del metodo DiscoveryProxy.OnBeginFind.Override the DiscoveryProxy.OnBeginFind method. Questo metodo viene chiamato quando il proxy di individuazione riceve una richiesta di ricerca.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. Eseguire l'override del metodo DiscoveryProxy.OnEndFind.Override the DiscoveryProxy.OnEndFind method. Questo metodo viene chiamato quando il proxy di individuazione completa l'elaborazione di una richiesta di ricerca.This method is called when the discovery proxy finishes processing a find request.

    protected override void OnEndFind(IAsyncResult result)  
            {  
                OnFindAsyncResult.End(result);  
            }  
    
  7. Eseguire l'override del metodo DiscoveryProxy.OnBeginResolve.Override the DiscoveryProxy.OnBeginResolve method. Questo metodo viene chiamato quando il proxy di individuazione riceve un messaggio di risoluzione.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. Eseguire l'override del metodo DiscoveryProxy.OnEndResolve.Override the DiscoveryProxy.OnEndResolve method. Questo metodo viene chiamato quando il proxy di individuazione completa l'elaborazione di un messaggio di risoluzione.This method is called when the discovery proxy finishes processing a resolve message.

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

I metodi OnBegin.The OnBegin.. / OnEnd./ OnEnd.. forniscono la logica per le operazioni di individuazione successive.methods provide the logic for the subsequent discovery operations. I metodi OnBeginFind e OnEndFind implementano ad esempio la logica di ricerca per il proxy di individuazione.For example the OnBeginFind and OnEndFind methods implement the find logic for discovery proxy. Quando il proxy di individuazione riceve un messaggio del probe, questi metodi vengono eseguiti per inviare una risposta al client.When the discovery proxy receives a probe message these methods are executed to send a response back to the client. È possibile modificare la logica di ricerca in base alle proprie esigenze. È ad esempio possibile incorporare un ambito personalizzato in base ad algoritmi o all'analisi dei metadati XML specifici dell'applicazione nell'ambito dell'operazione di ricerca.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.

Per implementare la classe AsyncResultTo implement the AsyncResult class

  1. Definire la classe di base astratta AsyncResult, utilizzata per derivare le varie classi AsyncResult.Define the abstract base class AsyncResult which is used to derive the various async result classes.

  2. Creare un nuovo file di codice denominato AsyncResult.cs.Create a new code file called AsyncResult.cs.

  3. Aggiungere le istruzioni using seguenti a AsyncResult.cs.Add the following using statements to AsyncResult.cs.

    using System;  
    using System.Threading;  
    
  4. Aggiungere la classe AsyncResult seguente.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);  
            }  
        }  
    

Per ospitare DiscoveryProxyTo host the DiscoveryProxy

  1. Aprire il file Program.cs nel progetto DiscoveryProxyExample.Open the Program.cs file in the DiscoveryProxyExample project.

  2. Aggiungere le istruzioni using riportate di seguito.Add the following using statements.

    using System;  
    using System.ServiceModel;  
    using System.ServiceModel.Discovery;  
    
  3. Aggiungere nel metodo Main() il codice riportato di seguito.Within the Main() method, add the following code. In questo modo viene creata un'istanza della classe DiscoveryProxy.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. Aggiungere quindi il codice seguente per aggiungere un endpoint di individuazione e un endpoint annunci.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();  
              }  
    

L'implementazione del proxy di individuazione è quindi completata.You have completed implementing the discovery proxy. Continuare a procedura: implementare un servizio individuabile che esegue la registrazione con il Proxy di individuazione.Continue on to How to: Implement a Discoverable Service that Registers with the Discovery Proxy.

EsempioExample

Quello che segue è l'elenco completo del codice usato in questo argomento.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();  
            }  
        }  
    }  
}  

Vedere ancheSee Also

Panoramica di WCF DiscoveryWCF Discovery Overview
Procedura: Implementare un servizio individuabile che esegue la registrazione al proxy di individuazioneHow to: Implement a Discoverable Service that Registers with the Discovery Proxy
Procedura: Implementare un'applicazione client che usa il proxy di individuazione per trovare un servizioHow to: Implement a Client Application that Uses the Discovery Proxy to Find a Service
Procedura: Testare il proxy di individuazioneHow to: Test the Discovery Proxy