Partager via


Étape 8 : Implémenter le gestionnaire de trafic entrant synchrone pour l’adaptateur Echo

Étape 8 sur 9

Durée d’exécution : 45 minutes

Au cours de cette étape, vous implémentez la fonctionnalité de trafic entrant de l’adaptateur d’écho. Cette fonctionnalité permet à l’adaptateur d’écouter les données ou les événements du système cible. Selon le Kit de développement logiciel (SDK) de l’adaptateur LOB WCF, vous devez uniquement implémenter l’interface Microsoft.ServiceModel.Channels.Common.IInboundHandler lorsque votre adaptateur prend en charge la fonctionnalité de trafic entrant. L’Assistant Développement d’adaptateur génère automatiquement la classe dérivée appelée EchoAdpterInboundHandler pour vous.

Dans la section suivante, vous allez mettre à jour la classe EchoAdpterInboundHandler pour mieux comprendre comment implémenter cette interface. Lorsque vous effectuez cette étape, vous disposez d’un gestionnaire entrant opérationnel pour l’adaptateur d’écho.

Prérequis

Avant de commencer cette étape, vous devez avoir effectué l’étape 7 : Implémenter le gestionnaire sortant synchrone pour l’adaptateur Echo. Une connaissance de base est Microsoft.ServiceModel.Channels.Common.IInboundHandler également utile.

The IInboundHandler Interface

Le Microsoft.ServiceModel.Channels.Common.IInboundHandler est défini comme :

public interface IInboundHandler : IConnectionHandler, IDisposable  
{  
          void StartListener(string[] actions, TimeSpan timeout);  
          void StopListener(TimeSpan timeout);  
          bool TryReceive(TimeSpan timeout, out Message message, out IInboundReply reply);  
          bool WaitForMessage(TimeSpan timeout);  
}  

Les descriptions des méthodes sont les suivantes :

Méthode Description
StartListener Commence à écouter les messages avec les actions WS-Addressing fournies. Si aucune n’est spécifiée, elle écoute toutes les actions ou les actions par défaut.
StopListener Cesse d’écouter.
TryReceive Tente de recevoir un message entrant du système cible.
WaitForMessage Attend un message WCF entrant à partir du système cible.

Pour plus d’informations sur la description de chaque paramètre de méthode, consultez la documentation sur l’interface Microsoft.ServiceModel.Channels.Common.IInboundHandler .

Implémentation de EchoAdpterInboundHandler

L’adaptateur d’écho utilise pour System.IO.FileSystemWatcher simuler le système cible. Dans ce qui suit, vous implémentez chaque méthode dans l’interface Microsoft.ServiceModel.Channels.Common.IInboundHandler , StartListener, StopListener, TryReceive et WaitForMessage.

Pour implémenter l’interface IInboundHandler dans la classe EchoAdpterInboundHandler

  1. Dans Explorateur de solutions, double-cliquez sur le fichier EchoAdapterInboundHandler.cs.

  2. Dans l’éditeur Visual Studio, ajoutez les lignes suivantes à l’ensemble existant de directives using.

    using System.IO;  
    using System.ServiceModel.Channels;  
    using System.Xml;  
    using System.Diagnostics;  
    
  3. Ajoutez maintenant des variables de niveau classe à la classe EchoAdapterInboundHandler. Ces variables sont utilisées pour surveiller l’activité des fichiers dans le système de fichiers. Copiez les déclarations ci-dessous dans la classe avant le constructeur.

    private Queue<Message> inboundQueue;  
    private FileSystemWatcher inboundWatcher;  
    private Object inboundQueueSynchronizationLock;  
    private string path;  
    private string filter;  
    
  4. Dans la méthode du constructeur EchoAdapterInboundHandler, ajoutez le code suivant pour initialiser l’infrastructure d’observation des fichiers et capturer le chemin d’accès et le filtre de surveillance.

    inboundWatcher = null;  
    inboundQueueSynchronizationLock = new Object();  
    path = connection.ConnectionFactory.Adapter.InboundFileSystemWatcherFolder;  
    filter = connection.ConnectionFactory.Adapter.InboundFileFilter;  
    
  5. Ajoutez maintenant le code suivant à la méthode StartListener . Le code implémente une logique pour vérifier les paramètres et démarrer la surveillance de l’activité des fichiers.

    // if no actions are provided, log an error in the trace log  
    // and throw an exception  
    if (actions.Length == 0)  
    {  
        EchoAdapterUtilities.Trace.Trace(TraceEventType.Error, "http://echoadapterv2/startlistener/noactions", "No operation actions were received for listener to do specific processing.", this);  
        throw new AdapterException("Unable to receive any actions for inbound handler to start listening.");  
    }  
    
    inboundQueue = new Queue<Message>();  
    foreach (string action in actions)  
    {  
        // for the OnReceiveEcho action listen for a new file created event  
        if ("Echo/OnReceiveEcho".Equals(action))  
        {  
            if (inboundWatcher == null)  
            {  
                inboundWatcher = new FileSystemWatcher(path);  
                inboundWatcher.Filter = filter;  
                // Begin monitoring  
                inboundWatcher.EnableRaisingEvents = true;  
            }  
            inboundWatcher.Created += new FileSystemEventHandler(FileMonitor_Created);  
            EchoAdapterUtilities.Trace.Trace(TraceEventType.Information, "http://echoadapterv2/startlistener", "Listening for file created event for " + filter + " in path " + path, this);  
        }  
    }  
    
  6. Continuez en ajoutant une implémentation pour la méthode StopListener .

    if (inboundWatcher != null)  
    {  
        // End monitoring  
        inboundWatcher.EnableRaisingEvents = false;  
        inboundWatcher = null;  
    }  
    lock (inboundQueueSynchronizationLock)  
    {  
        inboundQueue.Clear();  
        inboundQueue = null;  
    }  
    
  7. Fournissez maintenant une implémentation pour la méthode TryReveive . Cette méthode récupère le message de réception de fichier le plus récent de la file d’attente interne, le cas échéant.

    reply = new EchoAdapterInboundReply();  
    message = null;  
    TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);  
    while (true)  
    {  
        lock (inboundQueueSynchronizationLock)  
        {  
            if (inboundQueue == null)  
            {  
                //listener has been closed  
                return false;  
            }  
            if (inboundQueue.Count != 0)  
            {  
                message = inboundQueue.Dequeue();  
                if (message != null)  
                {  
                    return true;  
                }  
            }  
        }  
        if (timeoutHelper.IsExpired)  
        {  
            return false;  
        }  
        //wait for sometime, and check again  
        System.Threading.Thread.Sleep(500);  
    }  
    
  8. Continuez en ajoutant une implémentation pour la méthode WaitForMessage .

    while (inboundQueue.Count == 0) { };  
    Message msg = inboundQueue.Peek();  
    if (msg != null)  
    {  
        return true;  
    }  
    else  
    {  
        return false;  
    }  
    
  9. Fournissez maintenant le rappel pour l’observateur de fichiers. Pour ce faire, ajoutez la nouvelle méthode FileMonitor_Created à la classe EchoAdapterInboundAdapter .

    private void FileMonitor_Created(object sender, FileSystemEventArgs e)  
    {  
        lock (inboundQueueSynchronizationLock)  
        {  
            if (e.ChangeType == WatcherChangeTypes.Created)  
            {  
                // wait for file to close - should do this in a better manner  
                System.Threading.Thread.Sleep(500);  
                try  
                {  
                    EchoAdapterUtilities.Trace.Trace(TraceEventType.Information, "http://echoadapterv2/FileMonitorCreated", "File " + e.FullPath + " created.", this);  
                    FileInfo fileInfo = new FileInfo(e.FullPath);  
                    // Create WCF message to send to the inbound service  
                    // that is listening for messages from adapter  
                    String xmlData = String.Format(@"<OnReceiveEcho xmlns=""{0}""><path>{1}</path><length>{2}</length></OnReceiveEcho>", EchoAdapter.SERVICENAMESPACE, e.FullPath, fileInfo.Length);  
                    // set action string  
                    XmlReader reader = XmlReader.Create(new StringReader(xmlData));  
                    // create WCF message  
                    Message requestMessage = Message.CreateMessage(MessageVersion.Default  
                                , "Echo/OnReceiveEcho"  
                                , reader);  
                    requestMessage.Headers.To = new Uri(path);  
                    inboundQueue.Enqueue(requestMessage);  
                }  
                catch (Exception ex)  
                {  
                    String message = String.Format("An exception was thrown while trying to open file {1}.", e.FullPath);  
                    EchoAdapterUtilities.Trace.Trace(System.Diagnostics.TraceEventType.Error, "http://echoadapterv2/FileMonitorCreated", message, this, ex);  
                    throw new AdapterException(message, ex);  
                }  
            }  
        }  
    }  
    
  10. Vous devez maintenant supprimer les exceptions NotImplementedException levées par la classe EchoAdapterInboundReply interne. Pour ce faire, supprimez l’instruction suivante des méthodes Abort et Reply .

    throw new NotImplementedException("The method or operation is not implemented.");  
    

    Vos méthodes Abort et Reply doivent ressembler à ce qui suit.

    /// <summary>  
    /// Abort the inbound reply call  
    /// </summary>  
    public override void Abort()  
    {  
    }  
    
    /// <summary>  
    /// Reply message implemented  
    /// </summary>  
    public override void Reply(System.ServiceModel.Channels.Message message  
        , TimeSpan timeout)  
    {  
    }  
    
  11. Pour terminer l’implémentation du gestionnaire entrant, ajoutez la classe suivante à EchoAdapterOutboundHandler.cs. Cette classe fournit la prise en charge du délai d’expiration pour l’implémentation du gestionnaire entrant.

    /// <summary>  
    /// Utility class containing helper functions for measuring timeout   
    /// </summary>  
    class TimeoutHelper  
    {  
        private TimeSpan timeout;  
        private DateTime creationTime;  
        private Boolean isInfinite;  
    
        /// <summary>  
        /// Constructor  
        /// </summary>  
        /// <param name="timeout"></param>  
        public TimeoutHelper(TimeSpan timeout)  
        {  
            this.creationTime = DateTime.Now;  
            this.timeout = timeout;  
            if (timeout.Equals(Infinite)) this.isInfinite = true;  
        }  
    
        /// <summary>  
        /// Value of infinite timespan  
        /// </summary>  
        public static TimeSpan Infinite  
        {  
            get { return TimeSpan.MaxValue; }  
        }  
    
        /// <summary>  
        /// Value indicating remaining timeout  
        /// </summary>  
        public TimeSpan RemainingTimeout  
        {  
            get  
            {  
                if (this.isInfinite) return Infinite;  
                return this.timeout.Subtract(DateTime.Now.Subtract(this.creationTime));  
            }  
        }  
    
        /// <summary>  
        /// Get remaining timeout value and throw an exception if the timeout  
        /// has expired.  
        /// </summary>  
        /// <param name="exceptionMessage"></param>  
        /// <returns></returns>  
        public TimeSpan GetRemainingTimeoutAndThrowIfExpired(String exceptionMessage)  
        {  
            if (this.isInfinite) return Infinite;  
            if (RemainingTimeout < TimeSpan.Zero)  
            {  
                throw new TimeoutException(exceptionMessage);  
            }  
            return RemainingTimeout;  
        }  
    
        /// <summary>  
        /// Throw an exception if the timeout has expired.  
        /// </summary>  
        /// <param name="exceptionMessage"></param>  
        public void ThrowIfTimeoutExpired(String exceptionMessage)  
        {  
            if (RemainingTimeout < TimeSpan.Zero)  
            {  
                throw new TimeoutException(exceptionMessage);  
            }  
    
        }  
    
        /// <summary>  
        /// Value indicating whether timeout has expired.  
        /// </summary>  
        public Boolean IsExpired  
        {  
            get  
            {  
                if (this.isInfinite) return false;  
                return RemainingTimeout < TimeSpan.Zero;  
            }  
        }  
    }  
    
  12. Dans Visual Studio, dans le menu Fichier , cliquez sur Enregistrer tout.

  13. Dans le menu Générer, cliquez sur Générer la solution. Elle doit être compilée sans erreurs. Si ce n’est pas le cas, vérifiez que vous avez suivi toutes les étapes ci-dessus.

Notes

Vous avez enregistré votre travail. Vous pouvez fermer Visual Studio en toute sécurité à ce stade ou passer à l’étape suivante, Étape 9 : Générer et déployer l’adaptateur Echo.

Qu’est-ce que je viens de faire ?

Dans cette étape du didacticiel Sur l’adaptateur Echo, vous avez fourni une implémentation pour le gestionnaire entrant. Cette implémentation fournit des fonctionnalités d’observation de fichiers pour l’adaptateur Echo à l’aide de la classe FileSystemWatcher du .NET Framework.

Étapes suivantes

À l’étape suivante, vous déployez l’adaptateur.

Voir aussi

Étape 9 : Générer et déployer l’adaptateur Echo
Étape 7 : Implémenter le gestionnaire de trafic sortant synchrone pour l’adaptateur Echo