WCF Inversion of Control “Service Constructor” and better Unit Testing!

by David Kiff 28. August 2009 15:40

When creating a WCF service that is hosted in IIS using the .svc file, you need to specify the Service attribute in the directive.  The value of this service attribute is the fully qualified type name of service file (the one that contains the implementation of the service). 

<%@ ServiceHost Service="DavidKiff.Services.TimeService" Language="C#" %>

That service type is automatically created by WCF, which means you can not pass any of the dependencies into the constructor.  This means you can’t use a container to automatically wire-up the dependencies for you, nor can you easily unit test it. 

To get around this problem in the past, I create a new “Controller” class.  The service is responsible for constructing this class (and new-ing up its dependencies).  Each operation invoked in the service class is then directly passed to the controller to deal with.  Here is an example:

namespace DavidKiff.WCF
{
    [ServiceContract]
    internal interface ITimeService
    {
        [OperationContract]
        DateTime GetCurrentTime();
    }

    internal class TimeService : ITimeService
    {
        private readonly TimeServiceController _controller;
        public TimeService()
        {
            _controller = IoC.Resolve<ITimeServiceController>();
        }
        public DateTime GetCurrentTime()
        {
            return _controller.GetCurrentTime();
        }
    }

    internal class TimeServiceController
    {
        private readonly ILogger _logger;

        public TimeServiceController(ILogger logger)
        {
            _logger = logger;
        }

        public DateTime GetCurrentTime()
        {
            _logger.Log("Getting current time..");
            return DateTime.Now;
        }
    }
}

This approach allow me to unit test my controller, however its more of a work around than a real solution.  I still can’t test my service (although we have refactored out all the real logic) and we now have an additional controller class.

I recently discovered the use of the ServiceHostFactory.  This factory allows us to create our service (and pass it any dependencies) and pass it to the service host for hosting.

public class TimeServiceHostFactory : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        return new ServiceHost(IoC.Resolve<ITimeService>(), baseAddresses);
    }
}

To configure this in the ServiceHost directive we can use the Factory attribute.

<%@ ServiceHost Service="DavidKiff.Services.TimeService" Factory="DavidKiff.Services.TimeServiceFactory" Language="C#" %>

This approach now removes the need for the extra Controller class and allows me to pass in what I like to the Service class.

Tags: , ,

WCF

Comments

6/22/2010 3:21:54 AM #

pingback

Pingback from answers.hiwav.com

How to use dependency injection and the repository pattern with ASP.NET web services? | hiwav

answers.hiwav.com

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading