Partager via


Custom Demux

Cet exemple montre comment les en-têtes de message MSMQ peuvent être mappés à différentes opérations de service afin que les services Windows Communication Foundation (WCF) qui utilisent MsmqIntegrationBinding ne soient pas limités à l'utilisation d'une opération de service comme illustré dans les exemples Message Queuing to Windows Communication Foundation et Windows Communication Foundation to Message Queuing.

Dans cet exemple, le service est une application console auto-hébergée qui permet d'observer le service qui reçoit les messages mis en file d'attente.

Le contrat de service est IOrderProcessor, et il définit un service unidirectionnel pouvant être utilisé avec des files d'attente.

[ServiceContract]
[KnownType(typeof(PurchaseOrder))]
[KnownType(typeof(String))]
public interface IOrderProcessor
{
    [OperationContract(IsOneWay = true, Name = "SubmitPurchaseOrder")]
    void SubmitPurchaseOrder(MsmqMessage<PurchaseOrder> msg);

    [OperationContract(IsOneWay = true, Name = "CancelPurchaseOrder")]
    void CancelPurchaseOrder(MsmqMessage<string> ponumber);
}

Un message MSMQ n'a pas d'en-tête Action. Il n'est pas possible de mapper automatiquement différents messages MSMQ aux contrats d'opération. Par conséquent, il ne peut y avoir qu'un seul contrat d'opération. Pour passer outre cette limitation, le service implémente la méthode SelectOperation de l'interface IDispatchOperationSelector. La méthode SelectOperation permet au service de mapper un en-tête donné du message à une opération de service particulière. Dans cet exemple, l'en-tête d'étiquette du message est mappé aux opérations de service. Le paramètre Name du contrat d'opération détermine quelle opération de service doit être distribuée pour une étiquette de message donnée. Par exemple, si l'en-tête d'étiquette du message contient « SubmitPurchaseOrder », l'opération de service « SubmitPurchaseOrder » est appelée.

public class OperationSelector : IDispatchOperationSelector
{
    public string SelectOperation(ref System.ServiceModel.Channels.Message message)
    {
        MsmqIntegrationMessageProperty property = MsmqIntegrationMessageProperty.Get(message);
        return property.Label;
    }
}

Le service doit implémenter la méthode ApplyDispatchBehavior de l'interface IContractBehavior comme illustré dans l'exemple de code suivant. Le OperationSelector personnalisé est alors appliqué à l'exécution du répartiteur de l'infrastructure du service.

void IContractBehavior.ApplyDispatchBehavior(ContractDescription description, ServiceEndpoint endpoint, DispatchRuntime dispatch)
{
    dispatch.OperationSelector = new OperationSelector();
}

Un message doit traverser le ContractFilter du répartiteur avant d'arriver à OperationSelector. Par défaut, un message est rejeté si son action n'est trouvée sur aucun des contrats implémentés par le service. Pour éviter ce contrôle, nous implémentons un IEndpointBehavior nommé MatchAllFilterBehavior qui permet à tout message de traverser le ContractFilter, en appliquant le MatchAllMessageFilter comme suit.

public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher)
{
    endpointDispatcher.ContractFilter = new MatchAllMessageFilter();
}

Lorsqu'un message est reçu par le service, l'opération de service appropriée est distribuée à l'aide des informations fournies par l'en-tête d'étiquette. Le corps du message est désérialisé dans un objet PurchaseOrder, comme affiché dans l'exemple de code suivant.

[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void SubmitPurchaseOrder(MsmqMessage<PurchaseOrder> msg)
{
    PurchaseOrder po = (PurchaseOrder)msg.Body;
    Random statusIndexer = new Random();
    po.Status = (OrderStates)statusIndexer.Next(3);
    Console.WriteLine("Processing {0} ", po);
}

Le service est auto-hébergé. Lors de l'utilisation de MSMQ, la file d'attente utilisée doit être créée en avance. Cela peut s'effectuer manuellement ou via le code. Dans cet exemple, le service contient du code permettant de vérifier l'existence de la file d'attente et de la créer, si nécessaire. Le nom de la file d'attente est lu depuis le fichier de configuration.

public static void Main()
{
    // Get MSMQ queue name from app settings in configuration
    string queueName = ConfigurationManager.AppSettings["orderQueueName"];

    // Create the transacted MSMQ queue if necessary.
    if (!MessageQueue.Exists(queueName))
        MessageQueue.Create(queueName, true);

    // Create a ServiceHost for the CalculatorService type.
    using (ServiceHost serviceHost = new ServiceHost(typeof(OrderProcessorService)))
    {               
        ServiceEndpoint endpoint = serviceHost.Description.Endpoints[0];
        endpoint.Behaviors.Add(new MatchAllFilterBehavior());

        //Open the ServiceHost to create listeners and start listening for messages.
        serviceHost.Open();

        // The service can now be accessed.
        Console.WriteLine("The service is ready.");
        Console.WriteLine("Press <ENTER> to terminate service.");
        Console.ReadLine();

        // Close the ServiceHost to shutdown the service.
        serviceHost.Close();
    }
}

Le nom de la file d'attente MSMQ est spécifié dans la section appSettings du fichier de configuration.

ms752265.note(fr-fr,VS.90).gifRemarque :
Le nom de la file d'attente MSMQ comporte un point (.) pour l'ordinateur local et des barres obliques inverses comme séparateur dans son chemin d'accès. L'adresse du point de terminaison WCF spécifie un schéma msmq.formatname et utilise « localhost » pour l'ordinateur local. Une adresse de file d'attente correctement mise en forme d'après les règles d'adressage de nom du format MSMQ suit le schéma.

<appSettings>
    <!-- Use appSetting to configure the MSMQ queue name. -->
    <add key="queueName" value=".\private$\Orders" />
</appSettings>
ms752265.note(fr-fr,VS.90).gifRemarque :
Cet exemple requiert l'installation de Message Queuing (page pouvant être en anglais).

Démarrez le service et exécutez le client.

La sortie suivante s'affiche sur le client.

Placed the order:Purchase Order: 28fc457a-1a56-4fe0-9dde-156965c21ed6
        Customer: somecustomer.com
        OrderDetails
                Order LineItem: 54 of Blue Widget @unit price: $29.99
                Order LineItem: 890 of Red Widget @unit price: $45.89
        Total cost of this order: $42461.56
        Order status: Pending
Cancelled the Order: 28fc457a-1a56-4fe0-9dde-156965c21ed6
Press <ENTER> to terminate client.

La sortie suivante doit être vue sur le service.

The service is ready.
Press <ENTER> to terminate service.
Processing Purchase Order: 28fc457a-1a56-4fe0-9dde-156965c21ed6
        Customer: somecustomer.com
        OrderDetails
                Order LineItem: 54 of Blue Widget @unit price: $29.99
                Order LineItem: 890 of Red Widget @unit price: $45.89
        Total cost of this order: $42461.56
        Order status: Shipped
Purchase Order 28fc457a-1a56-4fe0-9dde-156965c21ed6 is cancelled

Pour configurer, générer et exécuter l'exemple

  1. Assurez-vous d'avoir effectué la procédure figurant dans la section Procédure d'installation unique pour les exemples Windows Communication Foundation.

  2. Pour générer l'édition C# ou Visual Basic .NET de la solution, suivez les instructions indiquées dans Génération des exemples Windows Communication Foundation.

  3. Pour exécuter l'exemple dans une configuration à un ou plusieurs ordinateurs, conformez-vous aux instructions figurant dans la rubrique Exécution des exemples Windows Communication Foundation.

Pour exécuter l'exemple sur plusieurs ordinateurs

  1. Copiez les fichiers de programme du service figurant dans le dossier \service\bin\ (situé dans le dossier correspondant à votre langue) sur l'ordinateur de service.

  2. Copiez les fichiers programme du client du dossier \client\bin\ (situé dans le dossier correspondant à votre langue) sur l'ordinateur client.

  3. Dans le fichier Client.exe.config, dans orderQueueName, remplacez « . » par le nom de l'ordinateur de service.

  4. Sur l'ordinateur de service, lancez Service.exe à partir d'une invite de commandes.

  5. Sur l'ordinateur client, lancez Client.exe à partir d'une invite de commandes.

Voir aussi

Autres ressources

Queuing in WCF
Message Queuing (page pouvant être en anglais)

Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.