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):队列服务的详细内容...