In this post I am going to show you the first steps in creating a solution for a max-strength Blogging Service solid enough to withstand any requirements change hurricane. This post will explore a little of the why’s and how’s of using dependency injection when hosting a REST service rather than providing a step-by-step guide on doing it. The final code for this post can however be downloaded at the bottom of this page.
We will see how to decouple a service from its’ hosting code using dependency injection (DI/IOC). Using a Visual Studio WCF REST service project as our starting point, then customising it to create a skeletal solution we will end up with a platform which is well positioned for developing in an Agile manner. For our dependency injection we are going to make use of Spring.Net which can be downloaded here.
Our max-strength service will initially be comprised of a Visual Studio solution with four projects. They are:
- Digiati.Services.Blogging.Host – Hosting functionality and config (WCF REST)
- Digiati.Services.Blogging.Service – Main service code (Class library)
- Digiati.Services.Blogging.Types – Publicly visible service types. i.e. Interfaces and DTOs (Class library)
- Digiati.Core.Service – Service activation, DependencyInjection, base classes etc. (Class library)
So, to get started, we create a new WCF REST Service project and call it Digiati.Services.Blogging.Host. This project is responsible for the service hosting, not the actual service code so we remove the cruft by deleting the generated Service1.cs and SampleItem.cs files and the App_Data folder.
Building the project now, gives a build error saying “The type or namespace name ‘Service1′ could not be found (are you missing a using directive or an assembly reference?)”. This is good news. One of the cornerstones of good software development is “Loose coupling, High cohesion”. What this means in English is the more classes your code compiles against, the less flexible it will become and when you write classes, keep them focused on the job at hand. By removing the Service1.cs file, we broke the coupling between the service hosting and the service implementation. This is good as it means we are reducing coupling but we are also increasing the cohesion of the host project (it only worries about hosting now). These two software engineering tenets make it easier for developers to maintain code since complexity is broken down and clarity increased.
The offending line of code with the build error is:
RouteTable.Routes.Add(new ServiceRoute ("Service1", new WebServiceHostFactory(), typeof(Service1)));
We are going to change this so that instead of using a WebServiceHostFactory we will create a custom service host factory which uses Spring.Net dependency injection to serve up a service into the host. We will also use the service interface class from our Types assembly (as opposed to it’s implementation) to instantiate the service at runtime on demand. The above line of code changes to:
RouteTable.Routes.Add(new ServiceRoute ("blogging", new DIServiceHostFactory(), typeof(IBloggingService)));
The DIServiceHostFactory code is based heavily on a great article written by Oran Dennison but we are going to make one small change so that we can instantiate a service class based on it’s interface. To do this, we need to have a convention for labelling object id’s in Spring.Net’s object configuration. We are going to use the fully qualified interface name as an object id to lookup the concrete class as below:
<object id="Digiati.Services.Blogging.Types.IBloggingService" type="Digiati.Services.Blogging.Types.BloggingService" />
Using the fully qualified interface name in this way means we get the best of two worlds – 1) Early binding against the interface compiled type and 2) decoupling from the concrete service implementation (The host project no longer has a reference to the service project. See code download for more). If we follow Oran’s article the one line we need to change is in the custom service host constructor where, instead of passing the actual service type through, we will ask Spring to use the interface type to return us a concrete class instead. The code below shows this:
public DIServiceHost(Type serviceType, params Uri baseAddresses): base(DependencyInjection.Create(serviceType.FullName).GetType(), baseAddresses)
One final note. The Host project has a post-build step to copy the service assembly into it’s bin directory so the Spring framework can find it. (We need to do this as we now only have a reference to the Types assembly).
So why are we going to all this trouble to decouple the service from it’s hosting? There are a few reasons actually:
- We can now implement Aspect Oriented Programming (AOP) at the service boundary using the Spring.Net framework (More on this in a later post).
- We can now easily reuse the service assembly in other projects. (Maybe in aggregated services, some sort of facade or public facing API).
- We are able to inject a different concrete service should we need to later.
- We can using mocking frameworks to test our hosting code.
- It just feels right and good and that makes us sleep easier at night.
In my next post I’ll get into another important aspect of extreme programming – Test Driven Development (TDD), and how it can be used to both test and define our implementation. Until then, feel free to download the code and have a play! Once built, run the Host project and browse to your service url such as: http://<install path>/blogging/ping.