Channel Factory and Caching

WCF client applications use the ChannelFactory<TChannel> class to create a communication channel with a WCF service. Creating ChannelFactory<TChannel> instances incurs some overhead because it involves the following operations:

  • Constructing the ContractDescription tree

  • Reflecting all of the required CLR types

  • Constructing the channel stack

  • Disposing of resources

To help minimize this overhead, WCF can cache channel factories when you are using a WCF client proxy.

Tip

You have direct control over channel factory creation when you use the ChannelFactory<TChannel> class directly.

WCF client proxies generated with ServiceModel Metadata Utility Tool (Svcutil.exe) are derived from ClientBase<TChannel>. ClientBase<TChannel> defines a static CacheSetting property that defines channel factory caching behavior. Cache settings are made for a specific type. For example, setting ClientBase<ITest>.CacheSettings to one of the values defined below will affect only those proxy/ClientBase of type ITest. The cache setting for a particular ClientBase<TChannel> is immutable as soon as the first proxy/ClientBase instance is created.

Specifying Caching Behavior

Caching behavior is specified by setting the CacheSetting property to one of the following values.

Cache Setting Value Description
AlwaysOn All instances of ClientBase<TChannel> within the app-domain can participate in caching. The developer has determined that there are no adverse security implications to caching. Caching will not be turned off even if "security-sensitive" properties on ClientBase<TChannel> are accessed. The "security-sensitive" properties of ClientBase<TChannel> are ClientCredentials, Endpoint and ChannelFactory.
Default Only instances of ClientBase<TChannel> created from endpoints defined in configuration files participate in caching within the app-domain. Any instances of ClientBase<TChannel> created programmatically within that app-domain will not participate in caching. Also, caching will be disabled for an instance of ClientBase<TChannel> once any of its "security-sensitive" properties is accessed.
AlwaysOff Caching is turned off for all instances of ClientBase<TChannel> of a particular type within the app-domain in question.

The following code snippets illustrate how to use the CacheSetting property.

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 { }

In the above code, all instances of TestClient will use the same channel factory.

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 {}

In the example above, all instances of TestClient would use the same channel factory except instance #4. Instance #4 would use a channel factory that is created specifically for its use. This setting would work for scenarios where a particular endpoint needs different security settings from the other endpoints of the same channel factory type (in this case 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 {}

In the example above, all instances of TestClient would use different channel factories. This is useful when each endpoint has different security requirements and it makes no sense to cache.

See also