改进
改进ClientBase性能的思路很简单:对ChannelFactory对象进行缓存。这与ASMX代理中的客户端类型缓存类似。
为ClientBase进行的ChannelFactory缓存。
核心思想是在AppDomain层缓存ChannelFactory对象, 这样一个ChannelFactory对象的生存时间就不由代理控制了。缓存是一种最常使用(most recently used, MRU)缓存。缓存大小被硬编码为32以便于将最少使用的ChannelFactory对象从缓存中移出。
由于有了ChannelFactory 缓存,创建一个ClientBase对象的粗略过程如下:
①在ClientBase构造函数中,会有一个lookup 方法在缓存中寻找一个匹配的ChannelFactory.
② 如果找到了,对这个ChannelFactory的引用数量会加1. 否则,会基于设置新创建一个ChannelFactory.
③ 在ClientBase的内部信道(传输代理)创建之前,如果其他公共属性(比如ChannelFactory, Endpoint和ClientCredentials)被访问过,那么当前ClientBase的缓存逻辑会被禁用。
④ 一旦内部信道被成功创建且ClientBase的ChannelFactory对象没有被从缓存中去除而且缓存没有被禁用,ChannelFactory对象会被添加到缓存中。
什么是匹配的ChannelFactory?
我之前说过”匹配的“ChannelFactory了吗?是的,你得保证你可以基于ClientBase构造函数中的输入设置来区分不同的ChannelFactory对象。有两种类型构造函数:将绑定作为参数的和不将绑定作为参数的。这里是那些不将绑定作为参数的:
ClientBase(string endpointConfigurationName);
ClientBase(string endpointConfigurationName, string remoteAddress);
ClientBase(string endpointConfigurationName, EndpointAddress remoteAddress);
ClientBase(InstanceContext callbackInstance);
ClientBase(InstanceContext callbackInstance, string endpointConfigurationName);
ClientBase(InstanceContext callbackInstance, string endpointConfigurationName, string remoteAddress);
ClientBase(InstanceContext callbackInstance, string endpointConfigurationName, EndpointAddress remoteAddress);
对这些构造函数来说,所有的参数(包括默认的那个)都在下面列表中:
string endpointConfigurationName
EndpointAddress remoteAddress
只要在构造ClientBase
这里是以绑定作为参数的两个构造函数:
ClientBase(InstanceContext callbackInstance, Binding binding, EndpointAddress remoteAddress);
既然绑定对象是不变的,比如,人们可以在一个代理上使用它,然后修改一下并在另外一个代理上使用,我们可以很容易地检查一个绑定对象是否有改动。因此当绑定被提供给构造函数时,对应代理的缓存机制被禁用。