By default, ConfigurationElementCollections don’t implement IEnumerable<T>, so if you are using custom configuration sections you can’t query them with linq. I found a casting solution, but I figured I could do better because the custom configuration classes are under my control, so it would be cleaner to implement the required functionality instead of using the clunky cast in the code consuming the collection. I implemented IEnumerable<T> against the ConfigurationElementCollection. It’s pretty straightforward, just calling the base class BaseGet function and casting the result properly using the As keyword. Now I can execute linq queries against my collection.
using System;
using System.Collections.Generic;
using System.Configuration;
namespace Config.Demo
{
public class MapConfig : ConfigurationSection
{
[ConfigurationProperty(“fields”)]
public MapConfigCollection Fields { get { return this[“fields”] as MapConfigCollection; } }
}
public class MapConfigElement : ConfigurationElement
{
[ConfigurationProperty(“server”)]
public string Server { get { return this[“server”] as string; } }
[ConfigurationProperty(“name”)]
public string Name { get { return this[“name”] as string; } }
[ConfigurationProperty(“id”)]
public int Id { get { return (int)this[“id”]; } }
}
public class MapConfigCollection : ConfigurationElementCollection, IEnumerable<MapConfigElement>
{
public MapConfigElement this[int index]
{
get { return base.BaseGet(index) as MapConfigElement; }
set
{
if (base.BaseGet(index) != null)
{
base.BaseRemoveAt(index);
this.BaseAdd(index, value);
}
}
}
protected override ConfigurationElement CreateNewElement()
{
return new MapConfigElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((MapConfigElement)element).Id;
}
#region IEnumerable<MapConfigElement> Members
public new IEnumerator<MapConfigElement> GetEnumerator()
{
int count = base.Count;
for (int i = 0; i < count; i++)
{
yield return base.BaseGet(i) as MapConfigElement;
}
}
#endregion
}
}