Sunday, September 05, 2004

Parsimonious parsing and System.Configuration

Not long after I got into .NET development, I learned of the System.Configuration namespace. Initially, I simply took advantage of using a simple <appSettings> section, and the corresponding System.Configuration.ConfigurationSettings.AppSettings NameValueCollection. For small amounts of application configuration, this has great appeal.

Later explorations led me to the use of custom sections with the configuration file. If you include a <configSections> section within your configuration file, you can list your custom configuration sections with child <section> elements. Each <section> element indicates a name for the section and a string that identifies the class (and containing assembly) that can interpret the section. The actual custom section can then appear lower down in the configuration file and can include much more complex data since it’s simply XML and you provide the class to interpret it.

So what’s involved in providing the class to read the custom section? Not much. It has to implement IConfigurationSectionHandler and provide its sole member, Create. When your code calls System.Configuration.ConfigurationSettings.GetConfig(<your section name>), the framework invokes your Create method to hydrate an object from the xml that is passed via the XmlNode section argument.

My early implementations of a Create method were crude. In a nutshell, the code I wrote traversed the XML DOM, interpreted the data therein, and stored it in a custom class that was the method’s return value. There is nothing wrong with doing it this way, but it is tedious and, as I later learned, unnecessary.

One of the fundamental principals I’ve learned over the years is that if you find yourself doing something tedious, it’s time to reexamine it and look for an easier (and usually more elegant) way. In the case of implementing IConfigurationSectionHandler::Create(), it is far easier to leverage the power of XML serialization than it is to parse the data yourself. I believe I first caught wind of this technique in an MSDN article, and if I can find it again, I’ll add it to this entry. The gist of the idea is that if your custom configuration data can be stored in a class that can be serialized to XML, then it can be deserialized from the XML fragment that is your custom configuration section.

Rather than create the class to hold my configuration information, I find it simpler to define the XML schema (xsd) file that describes it. The class definition can then be generated with

Xsd /classes config.xsd

Xsd generates the config.cs file for you that contains the class that can be deserialized from the xml section. Here is a snippet that shows how simple it is to implement the Create method using XML deserialization.

public object Create(object parent, object configContext, System.Xml.XmlNode Section) {

CheckerConfiguration Result;
XmlSerializer Hydrator;
XmlReader Reader;
Hydrator = new XmlSerializer(typeof(CheckerConfiguration));
Reader = new XmlNodeReader(section);
try {
Result = (CheckerConfiguration) Hydrator.Deserialize(Reader);
}
finally {
Reader.Close();
}
return Result;
}


0 Comments:

Post a Comment

<< Home