1. 程式人生 > >WCF系列教程之WCF實例化

WCF系列教程之WCF實例化

說明 con bind () 應用程序 ebe 控制臺應用程序 alt .text

本文參考自http://www.cnblogs.com/wangweimutou/p/4517951.html,純屬讀書筆記,加深記憶

一、理解WCF實例化機制

1、WCF實例化,是指對用戶定義的服務對象以及與其相關的實例上下文對象的生存期的控制,也就是說每一個服務類其實就是一個服務實例,客戶端在調用服務端中的服務方法時,需要實例化一個服務端代理類對象,實例化就是對這個對象的生命周期的管理。

技術分享

2、實例化行為(使用 System.ServiceModel.ServiceBehaviorAttribute.InstanceContextMode 屬性進行設置),InstanceContextMode屬性有兩個作用:

(1)、控制如何創建 InstanceContext 以響應傳入的消息

(2)、每個 InstanceContext 都與一個用戶定義服務對象相關聯,因此設置 InstanceContextMode 屬性也可以控制用戶定義服務對象的實例化

默認情況下,InstanceContextMode 枚舉定義了實例化模式。可以使用下列實例化模式:

(1)、PerCall:單調模式,為每個客戶端請求創建一個新的 InstanceContext(以及相應的服務對象)。

(2)、PerSession:會話模式,這是InstanceContextMode的默認值,為每個新的客戶端會話創建一個新的 InstanceContext(以及相應的服務對象),並在該會話的生存期內對其進行維護(這需要使用支持會話的綁定).

(3)、Single:單例模式,單個 InstanceContext(以及相應的服務對象)處理應用程序生存期內的所有客戶端請求。

二、實例化模式PerCall、PerSession、Single詳解

1、單調模式

單調模式中,WCF總是創建一個新的服務實例上下文來處理請求對象,即客戶端每調用一次方法就會創建一個實例上下文對象,調用完成靠GC完成釋放對象(但是GC的回收具有不確定性,所以會有延遲),在調用下一個方法會創建下一個實例上下文,因此,一個會話通道可能會出現多個實例上下文對象。

代碼實例:

技術分享

1、WCF服務層搭建:新建契約層、服務層、和WCF宿主,添加必須的引用(這裏不會的參考本人前面的隨筆),配置宿主,生成解決方案,打開Host.exe,開啟服務。具體的代碼如下:

IPerCall.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace IService
{
    [ServiceContract
    (
    SessionMode=SessionMode.Required
    )
    ]
    public interface IPerCall
    {
        [OperationContract]
        int AddMethod(int a, int b);
        [OperationContract]
        int AddMethod1(int a, int b);
        [OperationContract]
        string GetInstanceId();//獲取實例Id
        [OperationContract]
        int GetInstanceCount();    //獲取實例數
        [OperationContract]
        int GetOperationCount();    //獲取調用操作方法的計數器
        
    }
}

PerCall.cs

using IService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace Service
{
    [ServiceBehavior
    (
    InstanceContextMode=InstanceContextMode.PerCall//設置當前服務類的實例化模式為單調模式,每調用一次方法,生成一個上下文實例
    )]
    public class PerCall:IPerCall
    {
        int operationCount;
        static int instanceCount;
        string instanceId;
        public PerCall() {
            instanceCount++;
            instanceId = Guid.NewGuid().ToString();
        }
        public string GetInstanceId()
        {
            return instanceId;
        }

        public int GetOperationCount()
        {
            return operationCount;
        }

        public int AddMethod(int a, int b)
        {
            operationCount++;
            return a + b;
        }

        public int AddMethod1(int a, int b)
        {
            operationCount++;;
            return a + b;
        }


        public int GetInstanceCount()
        {
            return instanceCount;
        }
    }
}

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks;

namespace Host
{
    
    class Program
    {
        static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof(Service.PerCall))) 
            {
                host.Open();
                Console.WriteLine("服務已啟動,按任意鍵中止...");
                Console.ReadKey(true);
                host.Close();
            }
        }
    }
}

App.Config

<?xml version="1.0"?>
<configuration>
  <system.serviceModel>

    <services>
      <service name="Service.PerCall" behaviorConfiguration="mexBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:1234/PerCall/"/>
          </baseAddresses>
        </host>
        <endpoint address="" binding="wsHttpBinding" contract="IService.IPerCall" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior name="mexBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

ok,打開Host.exe

技術分享

服務開啟成功!

2、新建一個名為Client的客戶端控制臺應用程序,添加對http://localhost:1234/PerCall/的引用

(1)、單調模式

program.cs代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            Client.PerCallClientNS.PerCallClient client = new PerCallClientNS.PerCallClient();
            Console.WriteLine("1+2={0},這是第{1}個實例上下文對象,實例ID是:{2},方法的操作數:{3}", client.AddMethod(1, 2),client.GetInstanceCount(),client.GetInstanceId(),client.GetOperationCount());
            Console.WriteLine("3+3={0},這是第{1}個實例上下文對象,實例ID是:{2},方法的操作數:{3}", client.AddMethod1(3, 3), client.GetInstanceCount(), client.GetInstanceId(), client.GetOperationCount());
            Console.ReadKey();
        }
    }
}

技術分享

通過結果分析,客戶端通過會話通過每調用一次服務端的方法,就會創建一個服務端上下文實例,技術分享通過這個變量就可以看出

所以除非當前通道關閉,要不然只要調用一次當前服務端的方法,那麽實例樹還會繼續上升。

(2)、單例模式(Single)

在單例模式中,WCF只會創建一個實例上下文來處理服務的所有的請求調用對象,即PerCall只會被實例化一次,不管調用的請求對象是在同一個客戶端還是在不同的客戶端.

代碼實例,在上面代碼的基礎上將PerCall類的ServiceBehavior屬性

 [ServiceBehavior
    (
    InstanceContextMode=InstanceContextMode.PerCall//設置當前服務類的實例化模式為單調模式,每調用一次方法,生成一個上下文實例
    )]

修改成

[ServiceBehavior
    (
    InstanceContextMode=InstanceContextMode.Single//設置當前服務類的實例化模式為單例模式,只生成一個上下文實例,所以客戶端共享這一個實例
    )]

重新部署工程

技術分享

不管執行多少次,當前總是第一個實例,說明當前上下文只生成了一個,應為沒有執行構造函數,所以只能是1,但是操作數的增加,說明了,客戶端共享了這一個實例,只要當前通道不關閉,那麽操作數會一直增加。

(3)、會話模式(PerSession)

在會話模式(PerSession)中,WCF會對客戶端與服務端的每一個會話通道創建一個實例上下文。即不同的客戶端在各自的會話通道的實例上下文中處理請求對象。

在上面代碼的基礎上將PerCall類的ServiceBehavior屬性的InstanceContextMode,修改成

[ServiceBehavior
    (
    InstanceContextMode=InstanceContextMode.PerSession//設置當前服務類的實例化模式為會話模式,WCF會為每一個會話創建一個上下文實例
    )]

重新部署工程

技術分享

每調用一次客戶端,生成一個上下文實例,每次都是新的實例

WCF系列教程之WCF實例化