I'm trying to use the .Net confgiuration model to handle the ability to load and merge together a heirachy of configuration files in a similar way to how the heirachical ASP.Net web confgiuration files are merged together.
Thanks to the excellent Unraveling the Mysteries of .NET 2.0 Configuration series of articles I've figured out how to do most things, but I'm having some trouble specifying the exact heirachy of configuration files to be loaded. Just as with web.config files there can potentially be an infinite heirachy of configuration files to load and the rules about exactly which files should be included needs to be determined at runtime.
As an example of the sort of heirachy I'm talking about - if a user is working on a file "c:\User\jblogs\Documents\Projects\MyApp\AppFile12.txt" then I might want the following files to be included in the heirachy:
- c:\User\jblogs\Documents\Projects\MyApp\myapp.config
- c:\User\jblogs\Documents\Projects\myapp.config
- c:\User\jblogs\myapp.config
- c:\Program Files\MyApp\config\myapp.config
(Disclaimer: The above is a simplified example of what I want to achieve, but I think that if I can figure out how to do the above then I will have cracked it)
I've even tried looking at the web.config code in Reflector, but its tricky to understand exactly what's going on - can anyone who understands this a bit better points me in the right direction?
public class MyConfigObject
{
public class MyConfigObject( MyConfigObject parent )
{
// Copy constructor - don't alter the parent.
}
}
public class MyConfigHandler : IConfigurationSectionHandler
{
public object Create( object parent, object context, XmlNode section )
{
var config = new MyConfigObject( (MyConfigObject)parent );
// Process section and mutate config as required
return config;
}
}
Now when you need to apply numerous levels of configuration simply collect all the files to process in a stack working up from the directory the file is in and then process them in LIFO order by popping the stack.
var currentWorkingDirectory = Path.GetDirectoryName( "c:\\User\\jblogs\\Documents\\Projects\\MyApp\\AppFile12.txt" );
var currentDirectory = new DirectoryInfo( currentWorkingDirectory )
var userDataRootDirectory = new DirectoryInfo( "c:\\User\\jblogs\\" );
var configFilesToProcess = new Stack<string>();
do
{
// Search for myapp.config in currentDirectory
// If found push path onto configFilesToProcess
currentDirectory = currentDirectory.GetParent();
}
while( !currentDirectory.Equals( userDataRootDirectory )
var applicationConfigPath = "c:\\Program Files\\MyApp\\config\\myapp.config";
configFilesToProcess.Push( applicationConfigPath );
var configHandler = new MyConfigHandler();
object configuration = null;
object configContext = null; // no idea what this is but i think it is the entire config file
while( configFilesToProcess.Any() )
{
var configPath = configFilesToProcess.Pop();
// Load config file
var configNode = null; // Extract your config node using xpath
configuration = configHandler.Create( configuration, configContext, configNode );
}
Please note that the code shown above is not the prettiest but it shows the intent - i would suggest splitting it out into a number of separate well named methods that each do one thing and do it well =)