using System; using System.ServiceModel; /// /// Utility class to help with easy disposal of a client channel, even if that /// channel is in a faulted state. /// See http://thorarin.net/blog/post.aspx?id=5fe3b4b6-0e3e-463e-ac42-10c1c4808853 /// for a more thorough explanation of the problem and why this solution was chosen. /// public class Channel : IDisposable { private ICommunicationObject _channel; private Channel(ICommunicationObject channel) { _channel = channel; } /// /// Creates a wrapper around an ICommunicationObject, that will handle disposing /// of its resources. This prevents CommunicationObjectFaultedException from /// being raised when the object is disposed after another exception occurs. /// /// Any object implementing ICommunicationObject /// Instance of the Channel class that will handle disposal of the ICommunicationObject public static IDisposable AsDisposable(object client) { return new Channel((ICommunicationObject)client); } /// /// The fixed Dispose implementation. /// Calls the Close() method on the communication object, unless it is in /// the faulted state, in which case Abort() will be called. /// public void Dispose() { bool success = false; try { if (_channel.State != CommunicationState.Faulted) { _channel.Close(); success = true; } } finally { // The Close() method itself may actually raise an exception, which is why we // use a flag to make sure that Abort() will be called when that happens. if (!success) _channel.Abort(); } } }