カスタム Demux

Download sample

このサンプルでは、MSMQ メッセージ ヘッダーをさまざまなサービス操作にマッピングする方法を通して、MsmqIntegrationBinding を使用する Windows Communication Foundation (WCF) サービスで複数のサービス操作を使用できることを示します (「Windows Communication Foundation へのメッセージ キュー」と「Windows Communication Foundation でのメッセージ キュー」のサンプルでは 1 つだけ使用しています)。

このサンプルのサービスは自己ホスト型コンソール アプリケーションであるので、サービスを実行すると、キューに置かれたメッセージを受信するようすを観察できます。

サービス コントラクトは IOrderProcessor です。これは、キューでの使用に適した一方向サービスを定義します。

[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);
}

MSMQ メッセージには Action ヘッダーがないので、さまざまな MSMQ メッセージを操作コントラクトに自動的にマッピングすることはできません。したがって、存在する操作コントラクトは 1 つだけです。この制限を克服するために、サービスは IDispatchOperationSelector インターフェイスの SelectOperation メソッドを実装します。SelectOperation メソッドによって、メッセージの特定のヘッダーを特定のサービス操作にマッピングできるようになります。このサンプルでは、メッセージのラベル ヘッダーをサービス操作にマッピングします。操作コントラクトの Name パラメータは、特定のメッセージ ラベルに対してどのサービス操作をディスパッチするかを示します。たとえば、メッセージのラベル ヘッダーに "SubmitPurchaseOrder" が含まれている場合に、"SubmitPurchaseOrder" サービス操作を呼び出します。

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

サービスは IContractBehavior インターフェイスの ApplyDispatchBehavior メソッドを実装する必要があります。次のサンプル コードを参照してください。これによって、カスタムの OperationSelector がサービス フレームワークのディスパッチ ランタイムに適用されます。

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

メッセージが OperationSelector に到達するには、ディスパッチャの ContractFilter を通過する必要があります。既定の設定では、メッセージのアクションが、サービスによって実装されているどのコントラクトにも見つからない場合に、メッセージが拒否されます。この検査を回避するために、MatchAllFilterBehavior という名前の IEndpointBehavior を実装します。これは、次に示すように MatchAllMessageFilter を適用して、どのメッセージも ContractFilter を通過できるようにするものです。

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

メッセージをサービスが受信すると、ラベル ヘッダーからの情報を使用して該当するサービス操作がディスパッチされます。メッセージの本文が逆シリアル化されて PurchaseOrder オブジェクトが作成されます。次のサンプル コードを参照してください。

[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);
}

サービスは自己ホスト型です。MSMQ を使用するときは、使用するキューをあらかじめ作成しておく必要があります。手動で作成することもコードで作成することもできます。このサンプルでは、サービスのコードの中でキューの存在を確認し、存在しない場合は作成します。キュー名は構成ファイルから読み込まれます。

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();
    }
}

MSMQ キュー名は、構成ファイルの appSettings セクションで指定されます。

Noteメモ :

キューの名前では、ドット (.) を使用してローカル コンピュータを表し、バックスラッシュ (\) を使用してパスを区切ります。WCF エンドポイント アドレスでは msmq.formatname スキームが指定され、ローカル コンピュータを表す localhost が使用されます。このスキームの後には、MSMQ 形式名のアドレス指定ガイドラインに沿って正しく書式設定されたキューのアドレスが続きます。

<appSettings>
    <!-- Use appSetting to configure the MSMQ queue name. -->
    <add key="queueName" value=".\private$\Orders" />
</appSettings>
Noteメモ :

このサンプルを実行するには、メッセージ キューのインストールがインストールされている必要があります。

サービスを開始してクライアントを実行します。

クライアントには、次の出力が表示されます。

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.

サービスには、次の出力が表示されます。

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

サンプルをセットアップ、ビルド、および実行するには

  1. Windows Communication Foundation サンプルの 1 回限りのセットアップの手順」が実行済みであることを確認します。

  2. ソリューションの C# 版または Visual Basic .NET 版をビルドするには、「Windows Communication Foundation サンプルのビルド」の手順に従います。

  3. 単一コンピュータ構成か複数コンピュータ構成かに応じて、「Windows Communication Foundation サンプルの実行」の手順に従います。

サンプルを複数コンピュータで実行するには

  1. サービスのプログラム ファイルを、言語固有のフォルダにある \service\bin\ フォルダからサービスのコンピュータにコピーします。

  2. クライアントのプログラム ファイルを、言語固有のフォルダにある \client\bin\ フォルダからクライアントのコンピュータにコピーします。

  3. Client.exe.config ファイルを開き、orderQueueName を変更して "." の代わりにサービス コンピュータを指定します。

  4. サービス コンピュータで、コマンド プロンプトから Service.exe を起動します。

  5. クライアント コンピュータで、コマンド プロンプトから Client.exe を起動します。

関連項目

その他の技術情報

Queuing in WCF
メッセージ キューのインストール

Footer image

Copyright © 2007 by Microsoft Corporation.All rights reserved.