WCF初探-27:WCF中的实例化
理解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又会重新开始计数。
作者:wangweimutou
出处:https://www.cnblogs.com/wangweimutou/p/4517951.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?