A Generic, IDisposable WCF Service Client

Posted by Steve Wilkes on Geeks with Blogs See other posts from Geeks with Blogs or by Steve Wilkes
Published on Thu, 30 Jun 2011 18:18:49 GMT Indexed on 2011/07/01 0:22 UTC
Read the original article Hit count: 444

Filed under:

WCF clients need to be cleaned up properly, but as they're usually auto-generated they don't implement IDisposable. I've been doing a fair bit of WCF work recently, so I wrote a generic WCF client wrapper which effectively gives me a disposable service client.

The ServiceClientWrapper is constructed using a WebServiceConfig instance, which contains a Binding, an EndPointAddress, and whether the client should ignore SSL certificate errors - pretty useful during testing! The Binding can be created based on configuration data or entirely programmatically - that's not the client's concern.

Here's the service client code:

using System;
using System.Net;
using System.Net.Security;
using System.ServiceModel;

public class ServiceClientWrapper<TService, TChannel> : IDisposable
    where TService : ClientBase<TChannel>
    where TChannel : class
{
    private readonly WebServiceConfig _config;

    private TService _serviceClient;

    public ServiceClientWrapper(WebServiceConfig config)
    {
        this._config = config;
    }

    public TService CreateServiceClient()
    {
        this.DisposeExistingServiceClientIfRequired();

        if (this._config.IgnoreSslErrors)
        {
            ServicePointManager.ServerCertificateValidationCallback =
                (obj, certificate, chain, errors) => true;
        }
        else
        {
            ServicePointManager.ServerCertificateValidationCallback =
                (obj, certificate, chain, errors) => errors == SslPolicyErrors.None;
        }

        this._serviceClient = (TService)Activator.CreateInstance(
            typeof(TService),

           
this._config.Binding,
           
this._config.Endpoint);

        if (this._config.ClientCertificate != null)
        {
            this._serviceClient.ClientCredentials.ClientCertificate.Certificate =

               
this._config.ClientCertificate;
        }

        return this._serviceClient;
    }

    public void Dispose()
    {
        this.DisposeExistingServiceClientIfRequired();
    }

    private void DisposeExistingServiceClientIfRequired()
    {
        if (this._serviceClient != null)
        {
            try
            {
                if (this._serviceClient.State == CommunicationState.Faulted)
                {
                    this._serviceClient.Abort();
                }
                else
                {
                    this._serviceClient.Close();
                }
            }
            catch
            {
                this._serviceClient.Abort();
            }

            this._serviceClient = null;
        }
    }
}

A client for a particular service can then be created something like this:

public class ManagementServiceClientWrapper :
    ServiceClientWrapper<ManagementServiceClient, IManagementService>
{
    public ManagementServiceClientWrapper(WebServiceConfig config)
        : base(config)
    {
    }
}

...where ManagementServiceClient is the auto-generated client class, and the IManagementService is the auto-generated WCF channel class - and used like this:

using(var serviceClientWrapper = new ManagementServiceClientWrapper(config))
{
    serviceClientWrapper.CreateServiceClient().CallService();
}

The underlying WCF client created by the CreateServiceClient() will be disposed after the using, and hey presto - a disposable WCF service client.

© Geeks with Blogs or respective owner