WCF服务编程读书笔记(9):队列服务
Example 9-1. Implementing and consuming a queued service
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; namespace WCFServiceProgramming.Library { [ServiceContract] public interface IMyContract { [OperationContract(IsOneWay = true )] void MyMethod(); } public class MyService : IMyContract { public void MyMethod() { } } }View Code
Example 9-2. Disabling MSMQ security
<? xml version="1.0" ?> < configuration > < system.web > < compilation debug ="false" targetFramework ="4.0" /> </ system.web > < system.serviceModel > < services > < service name ="" > < endpoint name ="MyServiceQueue" address ="net.msmq://localhost/private/MyServiceQueue" binding ="netMsmqBinding" bindingConfiguration ="NoMSMQSecurity" contract ="IMyContract" /> </ service > </ services > < bindings > < netMsmqBinding > < binding name ="NoMSMQSecurity" > < security mode ="None" ></ security > </ binding > </ netMsmqBinding > </ bindings > </ system.serviceModel > </ configuration >View Code
Example 9-3. Verifying a queue on the host
using System; using System.Collections.Generic; using System.Linq; using System.Text; using WCFServiceProgramming.Library; using System.ServiceModel; using System.Messaging; namespace WCFServiceProgramming.Host { class Program { static void Main( string [] args) { ServiceHost host = new ServiceHost( typeof (MyService)); if (MessageQueue.Exists( @" .\privates$\MyServiceQueue " ) == false ) { MessageQueue.Create( @" .\private$\MyServiceQueue " , true ); } host.Open(); } } }View Code
Example 9-4. Creating the queues in ServiceHost<T>
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.ServiceModel.Description; using WCFServiceProgramming.Library; using System.Messaging; namespace WCFServiceProgramming.Host { public class ServiceHost<T> : ServiceHost { protected override void OnOpening() { foreach (ServiceEndpoint endpoint in Description.Endpoints) { QueuedServiceHelper.VerifyQueue(endpoint); } base .OnOpening(); } } public static class QueuedServiceHelper { public static void VerifyQueue(ServiceEndpoint endpoint) { if (endpoint.Binding is NetMsmqBinding) { string queue = GetQueueFromUri(endpoint.Address.Uri); if (MessageQueue.Exists(queue) == false ) { MessageQueue.Create(queue, true ); } } } static string GetQueueFromUri(Uri uri) { return @" .\privates$\ " + uri.LocalPath.ToString(); } } }View Code
Example 9-5. Verifying the queue by the client
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using WCFServiceProgramming.Library; using System.Messaging; namespace WCFServiceProgramming.Client { class MyContractClient : ClientBase<IMyContract> , IMyContract { public void MyMethod() { Channel.MyMethod(); } } class Program { static void Main( string [] args) { if (MessageQueue.Exists( @" .\private$\MyServiceQueue " ) == false ) { MessageQueue.Create( @" .\private$\MyServiceQueue " , true ); } MyContractClient proxy = new MyContractClient(); proxy.MyMethod(); proxy.Close(); } } }View Code
Example 9-6. Extending QueuedServiceHelper to verify the queue on the client side
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.ServiceModel.Description; namespace WCFServiceProgramming { public static class QueuedServiceHelper { public static void VerifyQueue<T>( string endpointName) where T : class { ChannelFactory <T> factory = new ChannelFactory<T> (endpointName); VerifyQueue(factory.Endpoint); } public static void VerifyQueue<T>() where T : class { VerifyQueue <T>( "" ); } // Same as Example 9-4 public static void VerifyQueue(ServiceEndpoint endpoint) { // ... } } }View Code
Example 9-7. Purging the queues on host shutdown during debugging
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.ServiceModel.Description; using WCFServiceProgramming.Library; using System.Messaging; using System.Diagnostics; namespace WCFServiceProgramming.Host { public static class QueuedServiceHelper { public static void PurgeQueue(ServiceEndpoint endpoint) { if (endpoint.Binding is NetMsmqBinding) { string queueName = GetQueueFromUri(endpoint.Address.Uri); if (MessageQueue.Exists(queueName) == true ) { MessageQueue queue = new MessageQueue(queueName); queue.Purge(); } } } static string GetQueueFromUri(Uri uri) { return @" .\privates$\ " + uri.LocalPath.ToString(); } } public class ServiceHost<T> : ServiceHost { protected override void OnClosing() { PurgeQueues(); // More cleanup if necessary base .OnClosing(); } [Conditional( " DEBUG " )] void PurgeQueues() { foreach (ServiceEndpoint endpoint in Description.Endpoints) { QueuedServiceHelper.PurgeQueue(endpoint); } } // More members } }View Code
Example 9-8. Participating in the playback transaction
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.Transactions; using System.Diagnostics; namespace WCFServiceProgramming.Library { [ServiceContract] public interface IMyContract { [OperationContract(IsOneWay = true )] void MyMethod(); } [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] public class MyService : IMyContract { [OperationBehavior(TransactionScopeRequired = true )] public void MyMethod() { Transaction transaction = Transaction.Current; Debug.Assert(transaction.TransactionInformation.DistributedIdentifier != Guid.Empty); } } }View Code
Example 9-9. Ignoring the playback transaction
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.Transactions; using System.Diagnostics; namespace WCFServiceProgramming.Library { [ServiceContract] public interface IMyContract { [OperationContract(IsOneWay = true )] void MyMethod(); } [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] public class MyService : IMyContract { public void MyMethod() { Transaction transaction = Transaction.Current; Debug.Assert(transaction == null ); } } }View Code
Example 9-10. Using a new transaction
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.Transactions; using System.Diagnostics; namespace WCFServiceProgramming.Library { [ServiceContract] public interface IMyContract { [OperationContract(IsOneWay = true )] void MyMethod(); } [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] public class MyService : IMyContract { public void MyMethod() { using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew)) { // ... scope.Complete(); } } } }View Code
Example 9-11. Nontransactional client of a sessionless queued endpoint
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using WCFServiceProgramming.Library; using System.Messaging; using System.Transactions; namespace WCFServiceProgramming.Client { class MyContractClient : ClientBase<IMyContract> , IMyContract { public void MyMethod() { Channel.MyMethod(); } } class Program { static void Main( string [] args) { using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Suppress)) { MyContractClient proxy = new MyContractClient(); proxy.MyMethod(); // Message posts to queue here proxy.MyMethod(); // Message posts to queue here proxy.Close(); } } } }View Code
Example 9-12. Transactional client of a queued sessionless endpoint
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using WCFServiceProgramming.Library; using System.Messaging; using System.Transactions; namespace WCFServiceProgramming.Client { class MyContractClient : ClientBase<IMyContract> , IMyContract { public void MyMethod() { Channel.MyMethod(); } } class Program { static void Main( string [] args) { using (TransactionScope scope = new TransactionScope()) { MyContractClient proxy = new MyContractClient(); proxy.MyMethod(); // Message posts to queue here proxy.MyMethod(); // Message posts to queue here proxy.Close(); scope.Complete(); } } } }View Code
Example 9-13. Implementing a sessionful queued service
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.Transactions; using System.Diagnostics; namespace WCFServiceProgramming.Library { [ServiceContract(SessionMode = SessionMode.Required)] public interface IMyContract { [OperationContract(IsOneWay = true )] void MyMethod1(); [OperationContract(IsOneWay = true )] void MyMethod2(); [OperationContract(IsOneWay = true )] void MyMethod3(); } public class MyService : IMyContract { [OperationBehavior(TransactionScopeRequired = true , TransactionAutoComplete = false )] public void MyMethod1() { } [OperationBehavior(TransactionScopeRequired = true , TransactionAutoComplete = false )] public void MyMethod2() { } [OperationBehavior(TransactionScopeRequired = true )] public void MyMethod3() { } } }View Code
Example 9-14. Transactional queued singleton
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.Transactions; using System.Diagnostics; namespace WCFServiceProgramming.Library { [ServiceContract(SessionMode = SessionMode.NotAllowed)] public interface IMyContract { [OperationContract(IsOneWay = true )] void MyMethod(); } [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ReleaseServiceInstanceOnTransactionComplete = false )] public class MySingleton : IMyContract, IDisposable { [OperationBehavior(TransactionScopeRequired = true )] public void MyMethod() { } public void Dispose() { } } }View Code
Example 9-15. Verifying a custom DLQ
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using System.ServiceModel.Description; using WCFServiceProgramming.Library; using System.Messaging; using System.Diagnostics; namespace WCFServiceProgramming.Host { public static class QueuedServiceHelper { public static void VerifyQueue(ServiceEndpoint endpoint) { if (endpoint.Binding is NetMsmqBinding) { string queueName = GetQueueFromUri(endpoint.Address.Uri); if (MessageQueue.Exists(queueName) == false ) { MessageQueue.Create(queueName, true ); } NetMsmqBinding binding = endpoint.Binding as NetMsmqBinding; if (binding.DeadLetterQueue == DeadLetterQueue.Custom) { Debug.Assert(binding.CustomDeadLetterQueue != null ); string dlq = GetQueueFromUri(binding.CustomDeadLetterQueue); if (MessageQueue.Exists(dlq) == false ) { MessageQueue.Create(dlq, true ); } } } } static string GetQueueFromUri(Uri uri) { return @" .\privates$\ " + uri.LocalPath.ToString(); } } }View Code
Example 9-16. DLQ service config file
Example 9-17. Obtaining the MsmqMessageProperty
Example 9-18. Implementing a DLQ service
Example 9-20. Configuring a poison message service
Example 9-21. A simple response service
Example 9-22. The ResponseContext class
Example 9-23. Client-side programming with a response service
Example 9-24. Service-side programming with a response service
Example 9-25. Implementing a response service
Example 9-26. The ResponseContext.Current property
Example 9-27. Deriving from ResponseClientBase<T>
Example 9-28. Implementing ResponseClientBase<T>
Example 9-29. Implementing ResponseScope<T>
Example 9-30. Queuing up a response as part of the playback transaction
Example 9-31. Responding in a new transaction
Example 9-32. Service-side configuration of the HTTP bridge
Example 9-33. Service-side implementation of the HTTP bridge
Example 9-34. Client-side configuration of the HTTP bridge
Example 9-35. Client-side implementation of the HTTP bridge
查看更多关于WCF服务编程读书笔记(9):队列服务的详细内容...