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-19. Poison message handling on MSMQ 4

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

原文地址:https://www.cnblogs.com/thlzhf/p/2779856.html