My contribution to the ClientBase and IDisposable discussion

It's well known that there can be some unexpected behavior when one uses ClientBase<T> as IDisposable.

Published on Thursday, 02 June 2011

It's well known that there can be some unexpected behavior when one uses ClientBase as IDisposable:

I guess I come down on the less popular side of the debate, because how ClientBase was implemented makes quite a bit of sense to me. I'm currently kinda off of ClientBase, however, for most things, so I guess I'm not really affected. This is how I'm currently doing most of my client-side work:

public class ServiceClient<T>
  {
      private ChannelFactory<T> m_factory;
  
      public ServiceClient(ChannelFactory<T> channelFactory)
      {
          m_factory = channelFactory;
      }
  
      public ServiceClient(string endpointConfigurationName) : this(new ChannelFactory<T>(endpointConfigurationName)) { }
  
      public ServiceClient(string endpointConfigurationName, EndpointAddress remoteAddress) : this(new ChannelFactory<T>(endpointConfigurationName, remoteAddress)) { }
  
      public R Execute<R>(Func<T, R> deleg)
      {
          var chan = m_factory.CreateChannel();
          var ico  = chan as ICommunicationObject;
  
          R ret;
  
          try
          {
              ico.Open();
              ret = deleg(chan);
          }
          finally
          {
              if( ico.State == CommunicationState.Opened )
                  ico.Close();
              else if( ico.State == CommunicationState.Faulted )
                  ico.Abort();
          }
  
          return ret;
      }
  
      public void Execute(Action<T> deleg)
      {
          Execute(c => { deleg(c); return true; });
      }
  }