在本次实验中你将会体会到三种不同的实例管理模式。打开Instance Management文件夹下的InstanceManagement.sln解决方案。解决方案中包含了一个简单的服务器端和客户端。它们都被配置为了BasicHttpBinding。
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
为了监视实例的创建、回收和状态,service端的代码在它的三个方法:构造函数、MyMethod()和Dispose()中都会显示一个MessageBox来表明状态。另外service中有一个m_Counter的int型字段,我们可以通过观察它来得知我们是不是获得了一个新的实例。
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
MyMethod方法同样还记录了session ID。
Client端的代码创建了一个代理来调用MyMethod()方法:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](/Images/OutliningIndicators/None.gif)
Client端同样记录了session ID。编译并运行程序。
Per-Call模式
Per-Call意味着对于两次client端的调用,你将会得到两个不同的实例。也就是说即使client端两次调用使用的是相同的代理,每一次调用服务器端实例构造函数都会被调用一次。m_Counter的值始终都是1。在函数返回后Dispose()方法都会在后台被执行。注意到,在Debug窗口中我们可以观察到session ID都是没有的。
我们也可以显示的将服务配置为Per-Call类型。只需要将InstanceContextMode属性设置为InstanceContextMode.PerCall即可:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
Per-Session模式
接下来,我们将会把服务配置为每个客户端都会关联到一个特定的服务,类似于经典的C/S模式。将服务器属性InstanceContextMode修改为InstanceContextMode.PerSession:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
你会看到,服务仍然是Per-Call的,并没有session。因为要将session设置为contract的一部分,这样才会有效果。打开MyService.cs文件,将service contract的SessionMode属性设置为
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/None.gif)
同样,在client端的Proxy.cs文件中也需要做这样的定义。
编译程序并运行,你会得到如下的异常:
这是因为BasicHttpBinding不支持session。打开app.config文件,将binding改为WSHttpBinding:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
在client端也做同样的设置。
编译后运行程序。这一次你将只会得到一个服务器实例,counter的数量会变为2,实例也仅仅是在client端关闭后调用一次。启动两个client程序观察一下呢?
单实例模式
第三种是单实例模式(Singleton),即所有client端都连接到同一个实例上。将服务器属性InstanceContextMode修改为InstanceContextMode.Single:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
编译并运行程序,你将会看到,在没有任何client调用的时候服务器端的构造函数已经执行了。点击client端的button两次,counter的数量应该为4。关闭client程序,Dispose方法仍然没有被调用。
单实例模式是不需要session的,将SessionMode=SessionMode.Required去掉再试试看呢。