How would I need to write my custom ConfigurationSection so that it is both a section handler and a configuration element collection?
Normally, you have one class that inherits from ConfigurationSection, which then has a property that is of a type that inherits from ConfigurationElementCollection, which then returns elements of a collection of a type that inherits from ConfigurationElement.  To configure that, you would then need XML that looks something like this:
<customSection>
  <collection>
    <element name="A" />
    <element name="B" />
    <element name="C" />
  </collection>
</customSection>
I want to cut out the <collection> node, and just have:
<customSection>
  <element name="A" />
  <element name="B" />
  <element name="C" />
<customSection>
I assume that the collection is a property of your custom ConfigurationSection class.
You can decorate this property with the following attributes:
[ConfigurationProperty("", IsDefaultCollection = true)]
[ConfigurationCollection(typeof(MyElementCollection), AddItemName = "element")]
A full implementation for your example could look like this:
public class MyCustomSection : ConfigurationSection
{
    [ConfigurationProperty("", IsDefaultCollection = true)]
    [ConfigurationCollection(typeof(MyElementCollection), AddItemName = "element")]
    public MyElementCollection Elements
    {
        get { return (MyElementCollection)this[""]; }
    }
}
public class MyElementCollection : ConfigurationElementCollection, IEnumerable<MyElement>
{
    private readonly List<MyElement> elements;
    public MyElementCollection()
    {
        this.elements = new List<MyElement>();
    }
    protected override ConfigurationElement CreateNewElement()
    {
        var element = new MyElement();
        this.elements.Add(element);
        return element;
    }
    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((MyElement)element).Name;
    }
    public new IEnumerator<MyElement> GetEnumerator()
    {
        return this.elements.GetEnumerator();
    }
}
public class MyElement : ConfigurationElement
{
    [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
    public string Name
    {
        get { return (string)this["name"]; }
    }
}
Now you can access your settings like this:
var config = (MyCustomSection)ConfigurationManager.GetSection("customSection");
foreach (MyElement el in config.Elements)
{
    Console.WriteLine(el.Name);
}
This will allow the following configuration section:
<customSection>
    <element name="A" />
    <element name="B" />
    <element name="C" />
<customSection>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With