Simplify configuration with a generic ConfigurationElementCollection class

I’ve been using Phil Haack‘s Custom Configuration Sections in 3 Easy Steps for some time now, and my configuration file management has never been happier… until I needed to read a collection of configuration elements.

Here’s a sample of the XML I needed to incorporate:

<importer>
	<filespecs>
		<add type="EmployeeCSV" path="d:\import\employees.csv" />
		<add type="OrderCSV" path="d:\import\orders_*.csv" />
	</filespecs>   
</importer>

The typical solution is to write your own collection class (FilespecConfigurationElementCollection), inheriting from ConfigurationElementCollection, and ensuring your Filespec object inherits from ConfigurationElement. I figured there has to be a better way — and there is.

I wrote a generic version of ConfigurationElementCollection, which you can use to avoid writing the custom collection class. The code that follows is the generic class, the Filespec object I used, and the property declaration from my ConfigurationSettings class (as described in Phil’s previously mentioned article).

Note one key part of this implementation: You must override the ToString() method of your custom ConfigurationElement class to return a unique value. The generic ConfigurationElementCollection uses the ToString() method to obtain a unique key for each element in the collection.

// The ConfigurationElementCollection<t> provides a simple generic implementation of ConfigurationElementCollection.
[ConfigurationCollection(typeof(ConfigurationElement))]
public class ConfigurationElementCollection</t><t> : ConfigurationElementCollection where T : ConfigurationElement, new()
{
	protected override ConfigurationElement CreateNewElement()
	{
		return new T();
	}
	protected override object GetElementKey(ConfigurationElement element)
	{
		return ((T)(element)).ToString();
	}
	public T this[int idx]
	{
		get { return (T)BaseGet(idx); }
	}
}
// The Filespec class is an example of a custom configuration element.
// Note that we inherit from ConfigurationElement, and use ConfigurationProperty attributes.
public class Filespec : ConfigurationElement
{
	public Filespec()
	{
	}
	[ConfigurationProperty("path", DefaultValue="", IsKey=true, IsRequired=true)]
	public string Path
	{
		get { return (string)(base["path"]); }
		set { base["path"] = value; }
	}
	[ConfigurationProperty("type", IsKey=false, IsRequired = true)]
	public FilespecType Type
	{
		get { return (FilespecType)(base["type"]); }
		set { base["type"] = value; }
	}

	public override string ToString()
	{
		return this.Path;
	}
}
// Finally, our ConfigurationSettings class (only part of the class is included).
// Note how we use the generic ConfigurationElementCollection.
public class ConfigurationSettings : ConfigurationSection
{
// ...
	[ConfigurationProperty("filespecs", IsRequired=true)]
	public ConfigurationElementCollection<filespec> FileSpecs
	{
		get { return (ConfigurationElementCollection</filespec><filespec>)this["filespecs"]; }
	}
// ...
}

If you’re using a number of ConfigurationElementCollections, this is a great way to simplify your code.

Posted in Uncategorized | Tagged

Article to appear in September 2004 DNDJ

I received word that my third article for .Net Developer’s Journal will appear in the September 2004 issue. It’s the third in the series of articles entitled, “C# and the .Net Framework: Tying It All Together”. The first article was in the January 2004 issue, the second article was in the May 2004 issue. Why such a delay between articles? They never told me they were publishing the first article, so I didn’t get the second article to them until after it printed. They never received the third article (which was originally sent in May 2004) and we didn’t catch up with each other until last month. I’m working on the fourth article now and hopefully it’ll be in the October or November issue.

Posted in Uncategorized | Tagged