CastleWindsor chained dependency
Source code is available here.
I recently had a problem where I wanted an MVC controller to use constructor injection of specified dependency and have that dependency load another specified dependency using Windsor.
For example, I have a message of the day controller and it can get messages from either a file or from a database. To support this I have a message of the day service which formats the text it retrieves from a message of the day loader.
But as I said I have two ways of loading the message, so for the sake of this demo I have two services and two loaders.
[caption id=“attachment_231” align=“aligncenter” width=“568”]Controller, service and loader dependencies[/caption]
I don’t want my controller to request a named instance, I just want to register the implementations in the installers and let Windsor do the rest.
If the controller is using the database service, I want the database service to use the database loader; if the controller is using the file service, I want the file service to use the file loader.
To support this I added a ContractInstaller as shown here.
1 public class ContractInstaller : IWindsorInstaller
2 {
3 public void Install(IWindsorContainer container, IConfigurationStore store)
4 {
5 container.Register(
6 Component.For<IMessageLoader>().ImplementedBy<MessageLoaderDatabase>()
7 ,Component.For<IMessageLoader>().ImplementedBy<MessageLoaderFile>()
8
9 ,Component.For<IMessageOfTheDayService>().ImplementedBy<MessageOfTheDayServiceDatabase>()
10 .DependsOn(Dependency.OnComponent<IMessageLoader, MessageLoaderDatabase>())
11
12 ,Component.For<IMessageOfTheDayService>().ImplementedBy<MessageOfTheDayServiceFile>()
13 .DependsOn(Dependency.OnComponent<IMessageLoader, MessageLoaderFile>())
14
15 ,Component.For<MessageOfTheDayController>().LifestyleTransient()
16 .DependsOn(Dependency.OnComponent<IMessageOfTheDayService, MessageOfTheDayServiceFile>())
17 );
18 }
19 }
In lines 6 and 7 I register the loaders (IMessageLoader
), and in lines 9 and 12 I register the the services (IMessageOfTheDayService
) and they in turn depend on the registered loaders.
In line 15 I register the controller (MessageOfTheDayController
) and its dependency on IMessageOfTheDayService
, in this case it is using MessageOfTheDayServiceFile
.
To use the MessageOfTheDayServiceDatabase
, change the dependency on line 16.
Be sure to load this before the ControllersInstaller
provided by the Windsor nuget or you will get a clash between the MessageOfTheDayController
loaded by both installers. To make sure this happens I alter the default Bootstrap
method in ContainerBootstrapper
to the following.
1 public static ContainerBootstrapper Bootstrap()
2 {
3 var container = new WindsorContainer().Install(
4 new ContractInstaller(),
5 new ControllersInstaller()
6 );
7
8 return new ContainerBootstrapper(container);
9 }
Now when you run the app, the controller will be instantiated with the MessageOfTheDayServiceDatabase which in turn will be instantiated with MessageLoaderDatabase.