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();
}
}
}