Generic services with Castle Windsor and Topshelf
Would it not be brilliant if we could write Windows services without worrying about the infrastructure elements of the services? You know the boring bits that seems the same for every Windows service. Or even better; we can change the behaviour of a Windows service by just copying new assemblies into the service’s folder?
Some context
The current project I am working on requires quite a few Windows services running, mainly running scheduled jobs via Quartz.Net and reacting to messages on MSMQ queues via Masstransit. We use Topshelf to write the services, which gives us more time to focus on the actual functionality of the service, and not the infrastructure of controlling Windows services. In conjunction with Topshelf we use Castle Windsor as Inversion of Control container which makes the services flexible and easy to configure. So when we write a new service, we create a console application, put the (same) Topshelf configuration in each console application, change the Windsor Castle configuration to load the appropriate components we need. And there is the service.
The problem is that each service looks basically the same. Just with a different configuration. So what we need to do is abstract the differences between the services, and somehow auto magically change the behaviour of the service based on the abstraction.
What do we want to archive?
- We want a generic application that can be run as a console application or installed as a Windows Service.
- The generic application should be able to install components defining the behaviour of the application dynamically
Side step
Quite a few tools are mentioned and used in the post, so here is a short explanation of each of the tools
- Topshelf – A framework to help with the development of Windows Services, and serves as a host for Windows Services. Topshelf will help us write a generic application that can run as either a console application of Windows Service.
- Castle Windsor – Castle Windsor is best of breed, mature Inversion of Control container available for .NET and Silverlight. Castle Windsor will be used to dynamically inject functionality into the generic application.
- Quartz.NET – The tool is mentioned but not used in the post, but a very useful tool. Quartz.NET is a full-featured, open source job scheduling system that can be used from smallest apps to large scale enterprise systems.
- MassTransit – The tool is not used in the post, but it is a great tool to be aware of. MassTransit is a lean service bus implementation for building loosely coupled applications using the .NET framework.
First steps – Generic application
The application builds a Topshelf configuration, and asks Topshelf to host an instance of ServiceRunner. Topshelf takes care of the Windows Service infrastructure, while still allowing the application to run as a console application.
Next steps – Implement the behaviour of the application dynamically
Castle Windsor allows numerous ways of installing components into the container. We are going to use some XML configuration in conjunction with Windsor installer instances to configure the container. For more Castle Windsor goodness.
The XML configuration in the app.config will allow us to defined which installers to run when the container gets instantiated. This is done by defining the following in your app.config
We now have a way of dynamically running Castle Windsor installers to change the behaviour of an application.
Action!
Implement a simple application to run inside the skeleton application
Create a class library project (not a console project!). This will be our application we want to run “inside” the skeleton application. Your application does not have to be limited to a single assembly.
The important part of the new application is to define what the skeleton application should install into the Castle Windsor container in order to get your application to work. For our example I want to start a Http Server (code from BitterCode) to serve web pages. To get the server to run I need to install:
- the startable facility. The facility is part of the Castle Windsor framework, allowing a developer to mark classes to be run automatically when the Windsor container gets instantiated. The marked classes will be stopped when the container is disposed of. This facility warrants a blog post of it’s own, but for this post just know the facility will start our LameHttpServer when the container is initiated, and stop the LameHttpServer when the application stops.
- install the Http Server
into the container. As the skeleton application is looking for instances of Windsor installers (IWindsorInstaller implementations), we write two installers to install the required components. The way these installers are written is irrelevant to the skeleton application. So use the very cool fluent registration from Castle Windsor.
Get the new application to work inside the skeleton application
This is a bit of a manual step, but it could be automated of course. Create a folder for the application, copy the binaries of the skeleton application and the new application to the folder. Update the Skeleton.Service.exe.config to tell the skeleton application which installers to run.
The following sequence of events occur to make the application run as expected
- The skeleton application instantiates a ServiceRunner instance
- ServiceRunner creates an instance of type IWindsorContainer using the skeleton.application.exe.config file
- The container reads the installers node
- Each installer defined is executed
- The application starts
Code
The code can be downloaded from https://github.com/rivethead/Public. To see the code in action, run Skeleton.Service.exe in the HttpServer folder, and go to http://localhost:8089/ in a browser.
Notes
- The Castle Windsor installer functionality is available from Windsor 2.5. I have used version 2.5.1.
- I am pretty sure you could use Binsor to achieve the same configuration, you would just need to change the way the container gets instantiated in the ServiceRunner.
