WCF初探-27:WCF中的例項化
阿新 • • 發佈:2020-07-15
理解WCF中的例項化機制
- “例項化”是指對使用者定義的服務物件以及與其相關的 InstanceContext 物件的生存期的控制。也就是說我們的客戶端程式在呼叫服務端方法時,需要例項化一個服務端代理類物件,例項化就是對這個物件的生命週期的管理(比如:代理服務物件的建立,物件呼叫服務端方法後需要對其進行的回收處理)。
- 例項化行為(使用 System.ServiceModel.ServiceBehaviorAttribute.InstanceContextMode 屬性進行設定)控制如何建立 InstanceContext 以響應傳入的訊息。預設情況下,每個 InstanceContext 都與一個使用者定義服務物件相關聯,因此設定 InstanceContextMode 屬性也可以控制使用者定義服務物件的例項化。InstanceContextMode 列舉定義了例項化模式。可以使用下列例項化模式:
- PerCall:單調模式,為每個客戶端請求建立一個新的 InstanceContext(以及相應的服務物件)。
- PerSession:會話模式,這是InstanceContextMode的預設值,為每個新的客戶端會話建立一個新的 InstanceContext(以及相應的服務物件),並在該會話的生存期內對其進行維護(這需要使用支援會話的繫結)。
- Single:單例模式,單個 InstanceContext(以及相應的服務物件)處理應用程式生存期內的所有客戶端請求。
單調模式(PerCall)下的服務例項
- 在單調模式(PerCall)中,WCF總是建立一個新的服務例項上下文來處理請求物件,即呼叫一次方法就會建立一個例項上下文物件,呼叫完成後依靠GC機制釋放物件(可能會有延遲),再呼叫下一個方法時也會建立一個新的服務例項上下文物件。因此,在一個服務通道會話中可能出現多個例項上下文物件
- 接下來我將通過示例來驗證單調模式下的例項處理請求的方式。解決方案的建立請參照WCF初探-26:WCF中的會話,此示例中,我們採用GetInstanceId()來獲取服務端例項化的次數,採用GetOperationCount()來獲取呼叫方法的計數器。ISampleMethod.cs的程式碼如下:
using System.ServiceModel; namespace Service{ [ServiceContract(SessionMode=SessionMode.Required)] public interface ISampleMethod{ [OperationContract]string MethodOne(string msg); [OperationContract] string MethodTwo(string msg); [OperationContract] int GetInstanceId(); //獲取服務例項ID [OperationContract] int GetOperationCount(); //獲取呼叫操作方法的計數器 }}
SampleMethod.cs的程式碼如下:
using System.ServiceModel; namespace Service{ [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] public class SampleMethod:ISampleMethod { static int instanceCount; int instanceId; int operationCount; public SampleMethod() { instanceCount++; instanceId = instanceCount; } public string MethodOne(string msg) { operationCount++; return "You called MethodOne return message is: " + msg; } public string MethodTwo(string msg) { operationCount++; return "You called MethodTwo return message is: " + msg; } public int GetInstanceId() { return instanceId; } public int GetOperationCount() { return operationCount; } } }
寄宿服務後,使用svcutil.exe生成客戶端代理類和配置檔案,客戶端參考程式碼如下:
class Program{ static void Main(string[] args){ SampleMethodClient client1 = new SampleMethodClient(); CallMethod(client1); SampleMethodClient client2 = new SampleMethodClient(); CallMethod(client2); Console.Read(); } static void CallMethod(SampleMethodClient client){ Console.WriteLine(client.MethodOne("MethodOne")); Console.WriteLine("InstanceId:{0},OperationCount:{1}", client.GetInstanceId(), client.GetOperationCount()); Console.WriteLine(client.MethodTwo("MethodTwo")); Console.WriteLine("InstanceId:{0},OperationCount:{1}", client.GetInstanceId(), client.GetOperationCount()); } }
執行結果如下:
- 執行結果說明如下:
- Client1呼叫MethodOne()時,會進入到SampleMethod建構函式此時instanceCount會加1,所以instanceId等於1,operationCount加1後的值為1.
- Client1呼叫GetInstanceId()時,會再次進入SampleMethod建構函式產生新的例項,由於instanceCount為靜態變數,所以再次加1後會變成2,所以instanceId等於2。operationCount的普通變數,所以例項化後不會記錄先前的值,呼叫GetOperationCount()時operationCount沒有加量操作。所以為預設值0.呼叫GetOperationCount()後instanceId的值等於3.
- Client1呼叫MethodTwo()時,又會進入到SampleMethod建構函式產生新的例項,所以instanceId的值就會等於4.再次呼叫GetInstanceId()時,新的例項值又會增加1,所以客戶端最終會輸出5.而呼叫的操作計數器始終為0.
- 其實就是客戶端每做一次呼叫操作,SampleMethod就會被例項化一次,由此我們可以檢視到instanceId和OperationCount值的變化。
單例模式(Single)下的服務例項
- 在單調模式(single)中,WCF只會建立一個例項上下文來處理服務的所有請求呼叫物件,即 SampleMethod只會進行一次例項化。不管呼叫的請求物件是在同一個客戶端還是在不同的客戶端。
- 要檢驗單調模式(single),我們只需把服務行為的InstanceContextMode設定為single,重新編譯工程後,執行結果如下:
- 執行結果說明:由於WCF採用單例模式只會生成一個例項化上下文,所以從執行的結果可以看到instanceId的值始終為1,而操作計數器OperationCount也在不斷做累加,再經過Client1和Client2呼叫處理後,在MethodOne()和MethodTwo()做累加,所以最終的值為4.
會話模式(PerSession)下的服務例項
- 在會話模式(PerSession)中,WCF會對客戶端與服務端的每一個會話通道建立一個例項上下文。即不同的客戶端在各自的會話通道的例項上下文中處理請求物件。
- 要檢驗會話模式(PerSession),我們只需把服務行為的InstanceContextMode設定為PerSession,重新編譯工程後,執行結果如下:
- 執行結果說明:從執行結果可以看出客戶端例項Client1的呼叫所在的instanceId為1,操作計數器OperationCount經過兩次的呼叫(呼叫MethodOne()和MethodTwo())後做累加,最後的值為2.客戶端Client2呼叫的時候會產生新的例項上下文。所以instanceId的值為2,操作計數器OperationCount又會重新開始計數。