通道工厂和缓存

WCF 客户端应用程序使用 ChannelFactory<TChannel> 类来创建 WCF 服务的通信通道。 创建 ChannelFactory<TChannel> 实例会带来一定的开销,因为这涉及以下操作:

  • 构造 ContractDescription

  • 反映所有所需的 CLR 类型

  • 构造通道堆栈

  • 资源的释放

为了尽量减少这种开销,WCF 可以缓存使用 WCF 客户端代理时的通道工厂。

提示

当直接使用 ChannelFactory<TChannel> 类时,您可以直接控制通道工厂创建。

使用 ServiceModel 元数据实用工具 (Svcutil.exe) 生成的 WCF 客户端代理派生自 ClientBase<TChannel>ClientBase<TChannel> 定义一个静态 CacheSetting 属性,该属性定义通道工厂缓存行为。 为特定类型设定缓存设置。 例如,将 ClientBase<ITest>.CacheSettings 设置为下面定义的一个值,将只会影响类型为 ITest 的那些代理/ClientBase。 特定 ClientBase<TChannel> 的缓存设置在创建第一个代理/ClientBase 实例后就不可改变。

指定缓存行为

缓存行为通过将 CacheSetting 属性设置为下列值之一指定。

缓存设置值 说明
AlwaysOn 应用程序域内的 ClientBase<TChannel> 的所有实例都可以参与缓存。 开发人员已经确定对缓存没有不利的安全性影响。 缓存不会关闭,即使访问了 ClientBase<TChannel> 上的“安全性敏感”属性。 ClientBase<TChannel> 的“安全性敏感”属性为 ClientCredentialsEndpointChannelFactory
Default 只有从在配置文件中定义的终结点创建的 ClientBase<TChannel> 的实例才参与应用程序域内的缓存。 以编程方式在应用程序域内创建的 ClientBase<TChannel> 的任何实例都将不参与缓存。 此外,只要访问 ClientBase<TChannel> 的实例的任何“安全性敏感”属性,就将为其禁用缓存。
AlwaysOff 在相关应用程序域内,已对特定类型的 ClientBase<TChannel> 的所有实例关闭缓存。

下面的代码段演示如何使用 CacheSetting 属性。

class Program
{
   static void Main(string[] args)
   {
      ClientBase<ITest>.CacheSettings = CacheSettings.AlwaysOn;
      foreach (string msg in messages)
      {
         using (TestClient proxy = new TestClient (new BasicHttpBinding(), new EndpointAddress(address)))
         {
            // ...
            proxy.Test(msg);
            // ...
         }
      }
   }
}
// Generated by SvcUtil.exe
public partial class TestClient : System.ServiceModel.ClientBase, ITest { }

在上述代码中,TestClient 的所有实例都将使用相同的通道工厂。

class Program
{
   static void Main(string[] args)
   {
      ClientBase<ITest>.CacheSettings = CacheSettings.Default;
      int i = 1;
      foreach (string msg in messages)
      {
         using (TestClient proxy = new TestClient ("MyEndpoint", new EndpointAddress(address)))
         {
            if (i == 4)
            {
               ServiceEndpoint endpoint = proxy.Endpoint;
               ... // use endpoint in some way
            }
            proxy.Test(msg);
         }
         i++;
   }
}

// Generated by SvcUtil.exe
public partial class TestClient : System.ServiceModel.ClientBase, ITest {}

在上述示例中,TestClient 的所有实例都将使用相同的通道工厂,实例 #4 除外。 实例 # 4 将使用专门供其使用而创建的通道工厂。 此设置适用于此类方案:特定终结点需要的安全设置不同于属于相同通道工厂类型(在此情况下为 ITest)的其他终结点。

class Program
{
   static void Main(string[] args)
   {
      ClientBase<ITest>.CacheSettings = CacheSettings.AlwaysOff;
      foreach (string msg in messages)
      {
         using (TestClient proxy = new TestClient ("MyEndpoint", new EndpointAddress(address)))
         {
            proxy.Test(msg);
         }
      }
   }
}

// Generated by SvcUtil.exe
public partial class TestClient : System.ServiceModel.ClientBase, ITest {}

在上面的示例中,TestClient 的所有实例将使用不同的通道工厂。 当每个终结点具有不同的安全需求并且对缓存没有意义时,这非常有用。

另请参阅