实例上下文管理着服务实例的生命周期。他有 System.ServiceModel.InstanceContext 类型表示,其中GetServiceInstance 和ReleaseServiceInstance 分别用于获得和释放服务实例。WCF 中有单调(PerCall)、会话(PerSession)和单例(Single)三种实例上下文模式。在服务行为特性(ServiceBehaviorAttribute)类型里有一个实例上下文模式(InstanceContextMode)的属性,通过该属性指定服务实例上下文模式。
在WCF中通过实例上下文提供者封装服务实例上下文。 它实现了接口 System.ServiceModel.Dispatcher.IInstanceContextProvider ,在该类型里面定义了根据请消息和服务信道获取现有服务实例上下文的方法 GetExistingInstanceContext ,用于初始化给定服务实例上下文的方法InitializeInstanceContext,判断实例上下文是否闲置以卸载上下文的 IsIdle 方法。WCF还提供了实例上下文初始化器(System.ServiceModel.Dispatcher.IInstanceContextInitializer) 和实例提供者(System.ServiceModel.Dispatcher.IInstanceProvider),这3个类型最终需要附加到分发运行时(System.ServiceModel.Dispatcher.DispatchRuntime)并成为运行时框架的一部分,分别对应分发运行时的 InstanceContextProvider、InstanceContextInitializers 和 InstanceProvider 三个属性。
对于服务实例的释放可以通过操作行为 (OperationBehaviorAttribute)特性控制释放操作执行的时机。在 OperationBehaviorAttribute 中有一个类型为 System.ServiceModel.ReleaseInstanceMode 的枚举属性,它定义了服务实例释放的模式,包括:BeforeCall (在操作方法执行前执行现有服务实例的释放)、BeforeAndAfterCall(在操作方法执行前和执行后执行现有服务实例的释放)、AfterCall(在操作方法执行后执行现有服务实例的释放)和 None (根据实例上下文题干中的IsIdle 方法的返回结果判断是否释放服务实例)。
单调实例上下文模式下,每一次服务调用请求时 WCF 都会创建一个新的服务实例上下文,在服务操作执行结束后释放服务上下文和服务实例。通过如下实例测试单调模式:
1: //服务单调模式
2: [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
3: public class CalculatorService : ICalculator, IDisposable
4: {
5: public CalculatorService()
6: {
7: Console.WriteLine("{0}:构造函数被执行。", Thread.CurrentThread.ManagedThreadId);
8: }
9: ~CalculatorService()
10: {
11: Console.WriteLine("{0}:终止器方法被执行。", Thread.CurrentThread.ManagedThreadId);
12: }
13: public void Dispose()
14: {
15: Console.WriteLine("{0}:Dispose 方法被执行。", Thread.CurrentThread.ManagedThreadId);
16: }
17: public int Add(int x, int y)
18: {
19: Console.WriteLine("{0}: Add 操作方法被执行[{1}]。", Thread.CurrentThread.ManagedThreadId,DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
20: return x + y;
21: }
22: }
客户端通过两次调用 Add 方法输出:
1: using (ChannelFactory<ICalculator> channelFacroy = new ChannelFactory<ICalculator>("CalculatorService_Client"))
2: {
3: ICalculator calculator = channelFacroy.CreateChannel();
4: calculator.Add(2,5);
5: calculator.Add(2, 5);
6: }
单例模式下,服务在寄宿的时候被创建唯一的一个服务实例上下文,并通过他处理所有的客户端服务调用请求。通过以下实例测试单例模式:
1: //单列模式下实例的创建与回收
2: [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
3: public class CalculatorService : ICalculator, IDisposable
4: {
5: public CalculatorService()
6: {
7: Console.WriteLine("{0}:构造函数被执行。", Thread.CurrentThread.ManagedThreadId);
8: }
9: ~CalculatorService()
10: {
11: Console.WriteLine("{0}:终止器方法被执行。", Thread.CurrentThread.ManagedThreadId);
12: }
13: public void Dispose()
14: {
15: Console.WriteLine("{0}:Dispose 方法被执行。", Thread.CurrentThread.ManagedThreadId);
16: }
17: public int Add(int x, int y)
18: {
19: Console.WriteLine("{0}: Add 操作方法被执行[{1}]。", Thread.CurrentThread.ManagedThreadId,DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
20: return x + y;
21: }
22: }
客户端通过创建两个服务代理调用 Add 方法输出:
1: using (ChannelFactory<ICalculator> channelFacroy = new ChannelFactory<ICalculator>("CalculatorService_Client"))
2: {
3: ICalculator calculator = channelFacroy.CreateChannel();
4: calculator.Add(2,5);
5: calculator.Add(2, 5);
6: ICalculator calculator2 = channelFacroy.CreateChannel();
7: calculator2.Add(5, 10);
8: }
WCF 中通过定义 System.ServiceModel.SessionMode 枚举类型表示会话模式,枚举值:Allowed(允许会话)、Required(强制会话)和 NotAllowed(不允许会话)。服务契约中定义了一个SessionMode的属性,通过 ServiceContractAttribute 特性执行会话模式,默认是 Allowed 。在操作契约中定义了会话初始(IsInitiating)和 会话终止(IsTerminating)两个属性,通过这两个属性可以控制操作方法执行初始初识或终止会话。要能实现会话,除了设置服务实例上下文模式为会话模式和服务契约允许会话或强制会话以外,还必须要能支持安全会话和可靠会话的绑定,NetTcpBinding、NetNamedPipeBinding、WSHttpBinding和WS2007Binding 这些绑定支持会话。通过以下实例测试会话模式:
定义强制会话的服务契约:
1: [ServiceContract(Namespace = "http://www.ainote.cn",SessionMode=SessionMode.Required)]
2: public interface ISessionCalculator
3: {
4: [OperationContract(IsInitiating = true, IsTerminating = false)]
5: void Reset();
6: [OperationContract(IsInitiating = false, IsTerminating = false)]
7: void Add(double x);
8: [OperationContract(IsInitiating = false, IsTerminating = true)]
9: double GetResult();
10:
11: }
定义支持会话模式的服务:
1: [ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
2: public class SessionCalculatorService:ISessionCalculator,IDisposable
3: {
4: public SessionCalculatorService() {
5: Console.WriteLine("{0}:构造器被执行。", Thread.CurrentThread.ManagedThreadId);
6: }
7: ~SessionCalculatorService() {
8: Console.WriteLine("{0}:终结器被执行。", Thread.CurrentThread.ManagedThreadId);
9: }
10: private double result = 0;
11: public void Reset() {
12: result = 0;
13: Console.WriteLine("{0}:Reset函数被执行。", Thread.CurrentThread.ManagedThreadId);
14: }
15: public void Add(double x) {
16: result += x;
17: Console.WriteLine("{0}:Add函数被执行。", Thread.CurrentThread.ManagedThreadId);
18: }
19: public double GetResult() {
20: Console.WriteLine("{0}:GetResult函数被执行。", Thread.CurrentThread.ManagedThreadId);
21: return result;
22:
23: }
24: public void Dispose() {
25: Console.WriteLine("{0}:Dispose被执行。", Thread.CurrentThread.ManagedThreadId);
26: }
27: }
客户端通过两个服务代理调用Add输出:
1: using (ChannelFactory<ISessionCalculator> channelFacroy = new ChannelFactory<ISessionCalculator>("SessionCalculatorService_Client"))
2: {
3: ISessionCalculator calculator1 = channelFacroy.CreateChannel();
4: calculator1.Reset();
5: calculator1.Add(12);
6: calculator1.Add(30);
7: (calculator1 as ICommunicationObject).Close();
8:
9: ISessionCalculator calculator2 = channelFacroy.CreateChannel();
10: calculator2.Reset();
11: calculator2.Add(12);
12: calculator2.Add(30);
13: (calculator2 as ICommunicationObject).Close();
14: Console.Read();
15: }
WCF 服务实例和会话主要用来维护服务实例的生命周期,不同实例上下文模式有所不同的适用业务场景。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。