I recently reused my generic, disposable WCF service client, and made some changes to make it simpler to use and easier to unit test. The original client was used like this:
using (var wrapper = new ServiceClientWrapper<
    ManagementServiceClient, IManagementService>(config))
{
    wrapper.CreateServiceClient().CallService();
}
…where config is a WebServiceConfig - a simple Data Bag which contains details of the service 
to call:
using System.Security.Cryptography.X509Certificates;
public class WebServiceConfig
{
    public string Binding { get; set; }
    public string Endpoint { get; set; }
    public bool IgnoreSslErrors { get; set; }
    public X509Certificate2 ClientCertificate { get; set; }
}
Having worked with the client on previous projects I’d noticed some problems with it; every time you 
use it you have to write a using statement and call CreateServiceClient(). That’s a minor 
inconvenience, but a bigger problem comes with unit testing code that uses it - newing up the 
ServiceClientWrapper makes it impossible to mock, 
but the class being IDisposable means it’s intended for one-shot uses and isn’t an appropriate 
candidate to be injected as a dependency. I 
worked around this by injecting in a ServiceClientWrapperFactory class which I could mock, but 
at some point I read Jimmy Bogard advise that your design may 
be flawed if you’re making objects which do nothing but create other objects, and while I generally 
have no problem changing a design to make it more testable, I knew this was one of those occasions.
So I had these problems to solve:
- Stop the user having to write 
usingstatements - Make the client injectable
 - Make the client mockable or stubbable
 - Get rid of the factory class which did nothing but make clients for unit tests
 
I’d also noticed a lot of boilerplate code to handle exceptions and retry service calls, and I wanted to get rid of that, too.
Thanks to these requirements, the class I wrote ended up being quite different to the previous client. 
It’s still IDisposable (more on why later) but it hides the process of creating and using a 
service client inside two Execute() methods. The previous client being constructed with a config 
limited its use to the service and setup defined therein - the new client is passed a config through 
its Execute() methods, which means the same instance can be used to call different services with 
different settings.
This is the new class I wrote:
using System;
using System.Net;
using System.Net.Security;
using System.ServiceModel;
public class ServiceClientWrapper<TClient, TService> : IDisposable
    where TClient : ClientBase<TService>, TService
    where TService : class
{
    private TClient _serviceClient;
    public void Execute(
        WebServiceConfig config,
        Action<TService> serviceCall,
        Action<CommunicationException> commsExceptionHandler = null,
        int numberOfTimesToRetry = 1)
    {
        Execute<object>(
            config,
            service => { serviceCall.Invoke(service); return null; },
            commsExceptionHandler,
            numberOfTimesToRetry);
    }
    public TResult Execute<TResult>(
        WebServiceConfig config,
        Func<TService, TResult> serviceCall,
        Action<CommunicationException> commsExceptionHandler = null,
        int numberOfTimesToRetry = 1)
    {
        SetupSecurity(config);
        var i = 0;
        CommunicationException thrownException = null;
        while (i < numberOfTimesToRetry)
        {
            DisposeExistingServiceClientIfRequired(); 
            try
            {
                return serviceCall
                    .Invoke(CreateServiceClient(config));
            }
            catch (CommunicationException faultEx)
            {
                thrownException = faultEx;
                if (commsExceptionHandler != null)
                {
                    try
                    {
                        commsExceptionHandler
                            .Invoke(thrownException);
                    }
                    catch (CommunicationException rethrownEx)
                    {
                        thrownException = rethrownEx;
                    }
                }
                ++i;
            }
            finally
            {
                DisposeExistingServiceClientIfRequired();
            }
        }
        throw thrownException;
    }
    private static void SetupSecurity(WebServiceConfig config)
    {
        if (config.IgnoreSslErrors)
        {
            ServicePointManager.ServerCertificateValidationCallback =
                (obj, certificate, chain, errors) => true;
        }
        else
        {
            ServicePointManager.ServerCertificateValidationCallback =
                (obj, certificate, chain, errors) => 
                    errors == SslPolicyErrors.None;
        }
    }
    protected virtual TService CreateServiceClient(
        WebServiceConfig config)
    {
        // Or you can use:
        // _serviceClient = (TClient)typeof(TClient).GetInstance(
        //     config.Binding,
        //     new EndpointAddress(config.Endpoint));
        _serviceClient = (TClient)Activator.CreateInstance(
            typeof(TClient),
            config.Binding,
            new EndpointAddress(config.Endpoint));
        return _serviceClient;
    }
    public void Dispose()
    {
        DisposeExistingServiceClientIfRequired();
    }
    private void DisposeExistingServiceClientIfRequired()
    {
        if (_serviceClient != null)
        {
            try
            {
                if (_serviceClient.State == CommunicationState.Faulted)
                {
                    _serviceClient.Abort();
                }
                else
                {
                    _serviceClient.Close();
                }
            }
            catch
            {
                _serviceClient.Abort();
            }
            _serviceClient = null;
        }
    }
}
At its simplest you use it like this - note that this time it’s a member of the class using it - it’s been injected in through the constructor, for instance:
_serviceClientWrapper.Execute(
    config,
    service => service.DoSomething());
If you have a service which returns a value, you can call it like this:
var response = _serviceClientWrapper.Execute(
    config,
    service => service.GetResponse());
If you want to handle CommunicationExceptions yourself, you can pass in a handler:
var response = _serviceClientWrapper.Execute(
    config,
    service => service.GetResponseWhichMightError(),
    commsException => SendMeAnEmailAboutThis(commsException));
…and if you want to retry a service call when CommunicationExceptions are thrown, you can pass 
in the number of times to retry:
var response = _serviceClientWrapper.Execute(
    config,
    service => service.GetUnreliableResponse(),
    commsException => SendMeAnEmailAboutThis(commsException),
    numberOfTimesToRetry: 3);
And so to the testability! Moving the WCF client creation code into a dedicated virtual 
CreateServiceClient method makes the client wrapper stubbable:
using System.ServiceModel;
public class StubServiceClientWrapper<TClient, TService> : 
    ServiceClientWrapper<TClient, TService>
    where TClient : ClientBase<TService>, TService
    where TService : class
{
    private readonly TService _serviceClientToReturn;
    public StubServiceClientWrapper(TService serviceClientToReturn)
    {
        _serviceClientToReturn = serviceClientToReturn;
    }
    protected override TService CreateServiceClient(
        WebServiceConfig config)
    {
        return _serviceClientToReturn;
    }
}
…where the stub is created with a TService instance to return from the overridden CreateServiceClient 
method. Then - as an example - a Service class like this:
public class Service
{
    private readonly WebServiceConfig _config;
    
    private readonly ServiceClientWrapper<
        ManagementServiceClient, IManagementService> 
            _serviceClientWrapper;
    public Service(
        WebServiceConfig config,
        ServiceClientWrapper<
            ManagementServiceClient, IManagementService> 
                serviceClientWrapper)
    {
        _config = config;
        _serviceClientWrapper = serviceClientWrapper;
    }
    public string GetResponse()
    {
        return _serviceClientWrapper.Execute(
            _config,
            serviceClient => serviceClient.GetResponse());
    }
}
…can be tested using a combination of the stub and a mock (using Moq in this case) like this:
var config = new WebServiceConfig
{
    Binding = "MyBinding",
    Endpoint = "http://service.com/Service.svc"
};
var wcfClient = new Mock<IManagementService>();
wcfClient.Setup(wcf => wcf.GetResponse()).Returns("Hello!");
var stubClientWrapper = new StubServiceClientWrapper<
    ManagementServiceClient, IManagementService>(
        wcfClient.Object);
var service = new Service(config, stubClientWrapper);
var serviceResponse = service.GetResponse();
Assert.AreEqual("Hello!", serviceResponse);
And there we have it - a unit-testable WCF service client wrapper. Because the stub only overrides the 
CreateServiceClient method everything else can be unit tested, including the retry and error-handling 
behaviour.
As mentioned, the new client wrapper is still IDisposable, even though you should never end up with 
an undisposed WCF client within it; I chose to leave it as IDisposable because classes with disposable 
members should themselves be disposable.
Comments
5 comments