Boilerplate anything bothers me and boilerplate XML even more so. I wanted a nice programmatic way for the users to say "configure the framework" in their application as a substitute for all the XML. What this meant, however, was that I now needed to configure the container 2 ways: programmatically using the fluent interface available in the trunk, and using a config file.
My first attempt went something like this:
WindsorContainer c = new WindsorContainer("dependencies.config");
c.Register(Component.For<IFrameworkThing>().ImplementedBy<FrameworkThing>();
c.AddFacility<RequiredFacility>();
While that looks ok, the order things happened bit me. Our facility (RequiredFacility in this example) happens to listen to the ComponentModelCreated event raised by the Kernel when a component is added to add a ComponentActivator (more specifics here). Since the XML gets processed (and all the components in it get added) before our facility is added, we miss the events we need to handle.
I needed a way to have my facility in place before adding in the stuff in the config. Due to a lack of documentation and the castle forums guys taking Thanksgiving off, I went down a bunch of fruitless avenues. I looked into loading the framework stuff into a parent container and then creating a child container with
WindsorContainer child =
new WindsorContainer(
parentContainerAlreadyConfigured,
"dependencies.config");
but the parent doesn't get the ComponentModelCreated events from the child.
Eventually I ended up with the following solution. This came from using Reflector (the best documentation for Castle I've found to date) and mimicking what the WindsorContainer constructor itself does.
WindsorContainer container = new WindsorContainer();
container.AddFacility<RequiredFacility>();
//other programmatic config
XmlInterpreter configInterpreter =
new XmlInterpreter("dependencies.config");
configInterpreter.ProcessResource(
configInterpreter.Source,
container.Kernel.ConfigurationStore);
container.Installer.SetUp(
container,
container.Kernel.ConfigurationStore);
The API seems a bit ugly, but it works. I get all the events I need and the users of the framework don't have to deal with any more boilerplate Windsor configuration.
Update: It turns out you can replace all the XmlInterpreter stuff with this:
container.Install(
Configuration.FromXmlFile("dependencies.config"));
This does the same stuff, only it looks a lot nicer.