There are a number of times when we've all had to implement new features or modify the implementation of an existing code base. An intern recently asked me how to feature toggle something using Castle.Windsor. This post will show how to use some Castle.Windsor features to toggle implementations. The example code can be found on GitHub.
The toggle will be an app setting in the application's config file. It will be loaded by Castle.Windsor by using a custom dependency resolver. This resolver is taken from Mark Seeman's post on AppSettings.
We'll be using a simple interface as our service definition. There will be two implementations. One represents an old implementation, the other a new.
It's useful to note that this is a common way to achieve some branching by abstraction. This is done by replacing calls to a service with an interface. This interface is the abstraction. Once the calls to the old service are replaced, you are free to implement a new service. When ready, the new service can be substituted for the old without the consumers being aware since they depend on the interface not the concrete.
Typed Factory Selector
Castle.Windsor comes with a handy little bit: the typed factory facility. The typed factory facility lets Castle.Windsor create a factory implementation from an interface defined by you. This relieves you of the task of implementing the factory on your own. It is especially useful if you want to defer the creation of the object.
Our class will use this factory to get an instance of our service, and call the .Print() method. The default for this object will be the first one registered in the container. This behavior can be overridden by implementing a custom selector.
The typed factory and selector must both be registered with the container. The selector must also be specified in the configuration of the typed factory. This is done on lines 21 and 22 of the ContainerFactory class.
Mike Hadlow provides a very good example of using a custom IHandlerSelector.
We can use a similar technique to pull in a config value and supply the appropriate implementation at run time. The custom IHandlerSelector uses the config value to select the appropriate handler. If no handlers are found it throws an exception. This handler is then returned.
This service handler must be registered and added to the container's kernel. Line 19 of the ContainerFactory class show the registration. Line 26 shows the selector being added to the kernel. While there is only one selector in this example, the snippet shows how to add more than one.
Running the Console
Changing the config value and running the console app shows that the selectors are functioning correctly.
Wrapping It Up
Feature toggles and branching by abstraction are powerful ways to control whether new code is being used in production. They provide a way to replace old behavior with new, while maintaining the integrity of the product's build. Hopefully these two examples will help you integrate feature toggling into your builds.