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

2 thoughts on “Simplify configuration with a generic ConfigurationElementCollection class”

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>