自訂 Demux
這個範例會示範 MSMQ 訊息標頭如何對應至不同的服務作業,以便讓使用 MsmqIntegrationBinding 的 Windows Communication Foundation (WCF) 服務不會受限於使用一項服務作業,如 訊息佇列至 Windows Communication Foundation 和 Windows Communication Foundation 至訊息佇列 範例所示。
這個範例中的服務是自我裝載的主控台應用程式,可讓您觀察接收佇列訊息的服務。
服務合約為 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 訊息自動對應至作業合約。因此,這時只能有一個作業合約。為了克服這項限制,服務會實作 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 區段中。
注意: |
---|
佇列名稱會使用點 (.)來代表本機電腦,並在其路徑中使用反斜線分隔符號。WCF 端點位址會指定 msmq.formatname 配置,並使用 localhost 表示本機電腦。在配置後面的是根據 MSMQ 格式名稱定址方針而正確格式化的佇列位址。 |
<appSettings>
<!-- Use appSetting to configure the MSMQ queue name. -->
<add key="queueName" value=".\private$\Orders" />
</appSettings>
注意: |
---|
這個範例需要安裝訊息佇列 (本頁面可能為英文)。 |
啟動服務,並執行用戶端。
下列輸出會顯示在用戶端上。
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
若要設定、建置及執行範例
若要建置方案的 C# 或 Visual Basic .NET 版本,請遵循建置 Windows Communication Foundation 範例中的指示。
若要在單一或跨機器的組態中執行本範例,請遵循執行 Windows Communication Foundation 範例中的指示。
若要跨機器執行範例
將語言特定資料夾下 \service\bin\ 資料夾中的服務程式檔複製到服務機器中。
將語言特定資料夾下 \client\bin\ 資料夾中的用戶端程式檔案複製到用戶端機器中。
在 Client.exe.config 檔案中,變更 orderQueueName 以取代 "." 指定服務機器名稱。
在服務機器上,從命令提示字元啟動 Service.exe。
在用戶端機器上,從命令提示字元啟動 Client.exe。
請參閱
其他資源
Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.