Friday, September 19, 2008

Configuration via IConfigurationSectionHandler

So I had an 'oh wow!' moment today - one of our application's requirements is to integrate with several shipping carrier APIs. My goal of course is to keep this as generic as possible - the application should not have any knowledge of the individual shippers, and should communicate with them via a single ShippingService implementation.

So far, so good - I've managed to unify the API of these disparate web services, but I had run into a stumbling block regarding how to configure these. After several false starts, my team lead suggested implementing IConfigurationSectionHandler. At first I balked (silently) - I can't stand dealing with 2.0 style Xml DOM objects, which IConfigurationSectionHandler uses - but after getting over myself I decided to take a look.

And I'm glad I did - IConfigurationSectionHandler is a *very* simple interface, exposing only a single method:

public object Create(object parent, object configContext, XmlNode section) {...}

For my purposes, 'parent' and 'configContext' weren't necessary - I only needed to concentrate on the 'section' argument. Implementing this was, as I expected, a bunch of Xml DOM code - but it wasn't so bad since the xml I'm working with is very simple.

One of my self-inflicted requirements was to keep the individual shipping carriers in separate assemblies, mostly to make adding a new carrier a no-rebuild operation. I want to be able to create the shipping carrier, drop its assembly into our Bin folder, add a configuration element, and go. So I made use of Assembly.Load to load the assembly in question, and Activator.CreateInstance to create an instance of the concrete carrier implementation. The constructor for the abstract Carrier type takes an IDictionary<string, string> of configuration properties (also gathered through my IConfigurationSectionHandler implementation) which the individual carrier will make use of - things like web service urls, etc.

I am in awe of how easy it was for all this to come together - it took maybe 2 hours, including MSDN browsing, to go from 0 knowledge of the problem to a working implementation that I'm comfortable putting into our production system.

Fun stuff! =)

No comments: