Home > General > WCF clients and IDisposable

WCF clients and IDisposable

There are numerous articles detailing the “broken” IDisposable implementation for WCF clients. Just to name a few:

To summarize, the Close() method will be called when the WCF client is disposed. However, if we try to dispose the client while it’s in a faulted state, an exception will be thrown.

The extension method provided in the CodeProject article allows you do something like this:

new MyTestClient().Using(x => x.DoSomething());

The Using() extension method will automatically close or abort the client once finished. However, I do not like this extension method. Without any explanation, a developer may mistakenly reuse the client:

var client = new MyTestClient();
client.Using(x => x.DoSomething());
client.Using(x => x.DoSomething());  // Connection is already closed.

Instead, I use this class:

public static class Client
{
    public static void Use<TClient>(Action<TClient> action)
        where TClient : ICommunicationObject, new()
    {
        var client = new TClient();

        try
        {
            action(client);
            client.Close();
        }
        catch (Exception)
        {
            client.Abort();
            throw;
        }
    }
}

… and the usage:

Client.Use<MyTestClient>(x => x.DoSomething());

One problem with the class above is that if we needed to instantiate the client using one of the overloaded constructors, we couldn’t due to the new() constraint. Instead, we can use this class:

public class Client<TClient>
    where TClient : ICommunicationObject
{
    private readonly TClient client;

    private Client(TClient client)
    {
        this.client = client;
    }

    public static Client<TClient> Instantiate(Func<TClient> action)
    {
        return new Client<TClient>(action());
    }

    public void Use(Action<TClient> action)
    {
        try
        {
            action(client);
            client.Close();
        }
        catch (Exception)
        {
            client.Abort();
            throw;
        }
    }
}

… and the usage:

Client<MyTestClient>
    .Instantiate(() => new MyTestClient("extra param"))
    .Use(x => x.DoSomething());
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: