views:

1276

answers:

3

I have a lot of castle xml configs where properties like connectionstring are also held under .Net configuration sections.

I'd like to be able to read out the properties using the container but can't see a mechanism to do it.

ie

<castle>
  <configuration>
    <properties>
      <connectionString>Data Source=MyServer;Initial Catalog=YadaYada;User      ID=me;Password=IAmGod</connectionString>
     </properties>
    <components>

...

Obviously the properties are there as there are component dependencies on them. I can resolve the components but not the properties.

Sure I could new up a component just to read out the property castle injected it, or I could wrap all the properties in a component specialised simply to hold name/val pairs. But I would have thought there be a simple container.resolve("property.connectionstring") notation.

*Edit Not very good with markdown, above was meant to be a xml section.

A: 

Aren't you thinking about this the wrong way round?

Surely the object that is using the connection string should have a ConnectionString property in the constructor and the dependency pushed in there with something in the components section of config like:

<component type="SessionManager">
  <parameters>
    <connectionString>#{connectionString}</connectionString>
  </parameters>
</component>

That way the connection string will automatically be passed in and your component won't need to know about the container at all - decoupled and cohesive!!!

Ronnie
No. My components all use the dependency just as you have posted. But I want to directly access the properties defined in the config file in code, just as you would with My.Setting.ConnectionString yada yada if you were using vanilla .NET config style
+2  A: 

You could do this a few different ways - for a strongly typed solution the obvious approach would be to implement a custom configuration class, then wire up the properties of the class with the properties in the windsor config (read-only properties with a bunch of constructor arguments would probably be best, so other dev's don't think they can update them) - there's a little bit of work in keeping the two in sync as you pointed out. Maybe write a small tool to parse the configuration files to generate the windsor config / class definition for this component, so you don't need to maintain it.

Another alternative would be to take the existing configuration interpreter and expose the properties that are collected while parsing the configuration - there would be a little bit of work (but not too much) to get at these .. I think you could do this by:

  • Creating a decorator implementing IXmlProcessorEngine that captures calls to AddProperty(XmlElement element) and stores the elements in it's own private dictionary.
  • Replace XmlProcessor with your own implementation (i.e. copy the source code for the class, then alter the constructor so that you wrap the decorator around the DefaultXmlProcessorEngine instance which is doing the actual work, so the various add-property calls are recorded).
  • Inherit from XmlInterpreter and override the ProcessResource method so that it calls your XmlProcessor replacement.
  • Decide how you want to get at the properties being stored by your decorator, perhaps it's configured with a dictionary that's passed in via constructor from the XmlInterpreter and XmlProcessor in turn..

Unfortunately AFAIK those properties aren't passed on to the configuration store, because they're only used during the interpretation stage - plus I don't believe the type converters are invoked at this stage of the parsing, so the values will be strings, but at least the if/else etc. condition statements will be evaluated correctly, as well as includes.

Bittercoder
I've implemented this suggestion (more or less). It feels like a really nasty hack, but it works. Cheers.
Damian Powell
+1  A: 

Answered here.

Mauricio Scheffer