Isolating WCF through Dependency Injection – Part I

25/06/2009

I have to admit that in the beginning I didn’t think Inversion of Control (IoC) Containers were that big of a deal. The idea of relying on an external agent to manage all the associations between objects in an application, sounded like it would bring more problems than advantages. Overkill. But I was wrong.

Since I began using IoC containers in my projects, I found that it naturally leads to loosely-coupled structures in the software. 
This is due to two key design principles that an IoC container will enforce you to follow:

  • Classes must explicitly state their dependencies with other classes as part of their public interface.
  • Classes never interact with each other directly, but only through interfaces that describe a set of capabilities in an abstract manner.

This decoupling contributes in making the software easily testable and ready for evolution.

Giving up control of WCF clients

In my last project I was designing classes that would need to interact with different Web Services through WCF client proxies.
I needed to test those classes in isolation in my unit tests, without having to have my WCF service host process running in the background, so I figured I would let an instance of a WCF proxy be pushed from outside the classes through an interface, as a dependency, instead of creating it internally, like I would normally do.

info This idea fits well with the way tools like svcutil and Visual Studio 2008 work when generating WCF client proxies, since they create a class as well as interfaces exposing the operations that can be invoked through the proxy.

So here is my first implementation:

public class MailClient
{
    private IMailServiceClientChannel proxy;

    public MailClient(IMailServiceClientChannel proxy)
    {
        this.proxy = proxy;
    }

    public EmailMessage[] DownloadMessages(string smtpAddress)
    {
        // Validate the specified Email address

        Mailbox request = new Mailbox(smtpAddress);
        EmailMessage[] response = proxy.GetMessages(request)

        // Do some processing on the results

        return response;
    }
}

Here I am using the IMailServiceClientChannel interface that is automatically generated by Visual Studio when adding a service proxy with the Add Service Reference dialog. This interface contains the signatures of all the operations that are part of the service contract, as well as WCF-specific infrastructure methods to manage the proxy, like Open and Close.

Something is missing

This didn’t feel quite right. I was not treating the WCF proxy like I should since I was not closing it properly after being done with it, and not having any sort of error handling code.

However, at a second thought, I realized this wasn’t really the responsibility of my class. Since I wasn’t creating the proxy instance myself but was instead receiving from the outside, I couldn’t really dispose it inside my method, because it could still be needed by the caller. So here is an alternative implementation:

public class MailClient
{
    private ChannelFactory<IMailServiceClientChannel> proxyFactory;

    public MailClient(ChannelFactory<IMailServiceClientChannel> proxyFactory)
    {
        this.proxyFactory = proxyFactory;
    }

    public EmailMessage[] DownloadMessages(string smtpAddress)
    {
        // Validate the specified Email address
        
        IMailServiceClientChannel proxy;
        
        try
        {
            proxy = proxyFactory.CreateChannel();

            Mailbox request = new Mailbox(smtpAddress);
            EmailMessage[] response = proxy.GetMessages(request)

            // Do some processing on the results

            proxy.Close();
            
            return response;
        }
        catch(Exception e)
        {
            proxy.Abort();

            throw new MailClientException("Failed to download Email messages", e);
        }
    }
}

This time instead of using a proxy instance, the class receives a ChannelFactory instance as an external dependency through the constructor.

infoChannel factories in WCF are the facilities used to create the pipelines, through which incoming and outgoing messages pass before being dispatched to the receiver or sent out over the wire.

This approach allows me to create a new proxy instances by invoking the ChannelFactory.CreateChannel method ad-hoc inside the class and to properly dispose them as soon as I no longer need them.

According to sources inside the WCF team at Microsoft, it is a best practice to create proxies by reusing the same ChannelFactory object, instead of creating a new proxy objects from the class generated by Visual Studio, since the cost of initializing the factory is paid only once.

This turns out to be a much better approach to assign WCF proxies to classes through Dependency Injection (DI) because now I can create instances of the MailClient class using my IoC of choice, which happens to be Microsoft Unity, with a couple of lines of code:

// Registers the ChannelFactory class with Unity
// and specifies the name of the endpoint to use
// as stated in the configuration file
var container = new UnityContainer();
container
    .RegisterType<ChannelFactory<IMailServiceClientChannel>>()
        .Configure<InjectedMembers>()
            .ConfigureInjectionFor<ChannelFactory<IMailServiceClientChannel>>(new InjectionConstructor("localMailServiceEndpoint"));

var client = container.Resolve<MailClient>();

// The object has now its dependencies already setup
// and is ready to be used
client.DownloadMessages("enrico@somedomain.com");

Here I’m registering the ChannelFactory class with the IoC container, telling it to pass the string “localMailServiceEndpoint” in the constructor whenever a new instance is created.
The ChannelFactory will use that value to look up in the configuration file the URL where the service is located and the protocol it should use to communicate with it, like in this sample WCF configuration:

<configuration>
    <system.serviceModel>
        <client>
            <endpoint
                name="localMailServiceEndpoint"
                address="http://localhost/mailservice"
                binding="wsHttpBinding"
                contract="IMailServiceClient" />
        </client>
    </system.serviceModel>
</configuration>

With this information in place, I’m now able to ask the container to construct an instance of the MailClient class, and it will automatically resolve the dependency on the WCF ChannelFactory for me.

What about testability?

Well, the ChannelFactory is a concrete class and, although certanly possible, can’t easily be faked out (through mocks or stubs) by using one of the common mocking isolation frameworks available out there, since it requires the presence of a configuration file with the proper WCF-specific settings in order to work correctly. This makes the MailClient class still hard to test in isolation.

In my next post I will explain a way to modify this sample to be able to write unit test for classes that use WCF proxies.

/Enrico

4 Responses to “Isolating WCF through Dependency Injection – Part I”

  1. Cyr1dian Says:

    Thanks for extra config!

    FYI I was using Unity to create a presenter as part of an MVP pattern. The presenter in turn used a WCF service as its model. This required a few interesting adaptations to your original solution.

    One minor thing in code fragment 3, line 7: “.Configure” should be “.Configure()”.

  2. colindooley Says:

    The one recurring and niggling thing I am getting for all the solutions presented on this subject is the depedence on either the ChannelFactory. or an Interfacefor a factory thereof. The usage of this class and what we have to do with it form a special case where the implementation is exposed to the client. We might as well just have the concrete proxy used. Why this niggles so much is that lets say you wanted to swap the proxy for a inline data service (i.e not a Web service) you cant do it, because you have leaked Channel implementation all over your method. ideally a completely clean call is need so that regardless of a WCF or direct data layer call you can swap out and mock.


    • @colindooley Thanks for your comment. You’re right, this solution does expose WCF-specific types to the consumer. The reason for that is simple: abstracting WCF away wasn’t the original purpose. The main goal was to allow the consumer of a service to control the lifetime of the client-side proxies used to communicate with that service.

      This post is now almost 4 years old and I’ve since changed the way I use WCF in my code in order to make it testable. As a matter of fact I’m currently working on a blog post just on that subject. Stay tuned.


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 )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 186 other followers