Demux personalizzato
Questo esempio dimostra il mapping di intestazioni di messaggio MSMQ su diverse operazioni del servizio in modo che i servizi Windows Communication Foundation (WCF) che utilizzano MsmqIntegrationBinding non siano limitati all'utilizzo di un'operazione del servizio come è dimostrato negli esempi Accodamento messaggi in Windows Communication Foundation e Da Windows Communication Foundation a Accodamento messaggi.
Il servizio, in questo esempio è un'applicazione console indipendente che consente di osservare il servizio che riceve messaggi in coda.
Il contratto di servizio è IOrderProcessor
e definisce un servizio unidirezionale adatto per l'utilizzo con le code.
[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 messaggio MSMQ non dispone di un'intestazione Action. Non è possibile eseguire automaticamente il mapping di messaggi MSMQ diversi su contratti dell'operazione. Pertanto, può essere presente un solo contratto dell'operazione. Per superare questa limitazione il servizio implementa il metodo SelectOperation dell'interfaccia IDispatchOperationSelector. Il metodo SelectOperation consente al servizio di eseguire il mapping di una determinata intestazione del messaggio con una particolare operazione del servizio. In questo esempio, l'intestazione dell'etichetta del messaggio è mappata sulle operazioni del servizio. Il parametro Name
del contratto dell'operazione determina quale operazione del servizio deve essere distribuita per una determinata etichetta del messaggio. Ad esempio, se l'intestazione dell'etichetta del messaggio contiene "SubmitPurchaseOrder", viene richiamata l'operazione del servizio "SubmitPurchaseOrder".
public class OperationSelector : IDispatchOperationSelector
{
public string SelectOperation(ref System.ServiceModel.Channels.Message message)
{
MsmqIntegrationMessageProperty property = MsmqIntegrationMessageProperty.Get(message);
return property.Label;
}
}
Il servizio deve implementare il metodo ApplyDispatchBehavior dell'interfaccia IContractBehavior come illustrato nel codice di esempio seguente. Questo applica l'OperationSelector
personalizzato al runtime di distribuzione del framework del servizio.
void IContractBehavior.ApplyDispatchBehavior(ContractDescription description, ServiceEndpoint endpoint, DispatchRuntime dispatch)
{
dispatch.OperationSelector = new OperationSelector();
}
Prima di arrivare a OperationSelector, un messaggio deve passare attraverso il ContractFilter del dispatcher. Per impostazione predefinita un messaggio viene rifiutato se non è possibile trovare la relativa azione in alcun contratto implementato dal servizio. Per evitare questo controllo, viene implementato un IEndpointBehavior denominato MatchAllFilterBehavior
, che consente il passaggio di tutti i messaggi attraverso il ContractFilter
applicando MatchAllMessageFilter nel modo seguente.
public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.ContractFilter = new MatchAllMessageFilter();
}
Quando il servizio riceve un messaggio, l'operazione del servizio appropriata viene distribuita utilizzando le informazioni fornite dall'intestazione dell'etichetta. Il corpo del messaggio viene deserializzato in un oggetto PurchaseOrder
, come illustrato nel codice di esempio seguente.
[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);
}
Il servizio è indipendente. Quando si utilizza MSMQ, la coda utilizzata deve essere creata in anticipo. Questa operazione può essere eseguita manualmente o mediante il codice. In questo esempio, il servizio contiene il codice necessario per verificare l'esistenza della coda e la crea se necessario. Il nome della coda viene letto dal file di configurazione.
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();
}
}
Il nome della coda MSMQ è specificato in una sezione appSettings del file di configurazione.
Nota
Nel nome della coda viene utilizzato un punto (.) per il computer locale e il separatore barra rovesciata nel percorso. Nell'indirizzo dell'endpoint di WCF viene specificato uno schema msmq.formatname e viene utilizzato "localhost" per il computer locale. Ciò che segue lo schema è un indirizzo di coda formattato correttamente in base alle linee guida sull'indirizzamento dei nomi del formato MSMQ.
<appSettings>
<!-- Use appSetting to configure the MSMQ queue name. -->
<add key="queueName" value=".\private$\Orders" />
</appSettings>
Nota
Questo esempio richiede l'installazione di Accodamento messaggi.
Avviare il servizio ed eseguire il client.
Sul client viene visualizzato l'output seguente.
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.
Nel servizio deve essere visualizzato l'output seguente.
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
Per impostare, compilare ed eseguire l'esempio
Assicurarsi di avere eseguito la Procedura di installazione singola per gli esempi di Windows Communication Foundation.
Per compilare l'edizione in C# o Visual Basic .NET della soluzione, seguire le istruzioni in Generazione degli esempi Windows Communication Foundation.
Per eseguire l'esempio su una configurazione con un solo computer o tra computer diversi, seguire le istruzioni in Esecuzione degli esempi di Windows Communication Foundation.
Per eseguire l'esempio tra più computer
Copiare i file del programma servizio dalla cartella \service\bin\, nella cartella specifica del linguaggio, al computer del servizio.
Copiare i file del programma client dalla cartella \client\bin\, nella cartella specifica del linguaggio, al computer client.
Nel file Client.exe.config, modificare l'orderQueueName per specificare il nome del computer del servizio anziché " ".
Sul computer del servizio, eseguire Service.exe da un prompt dei comandi.
Sul computer client, avviare Client.exe da un prompt dei comandi.
Vedere anche
Altre risorse
Queuing in WCF
Accodamento messaggi
Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.