Как сделать мой пользовательский раздел конфигурации похожим на коллекцию?

Как мне нужно написать свой пользовательский ConfigurationSection, чтобы он был как обработчиком раздела, так и коллекцией элементов конфигурации?

Обычно у вас есть один класс, который наследует от ConfigurationSection, который затем имеет свойство, которое имеет тип, наследуемый от ConfigurationElementCollection, который затем возвращает элементы коллекции типа, который наследуется от ConfigurationElement. Чтобы настроить это, вам понадобится XML, который выглядит примерно так:

<customSection>
  <collection>
    <element name="A" />
    <element name="B" />
    <element name="C" />
  </collection>
</customSection>

Я хочу вырезать <collection> node и просто иметь:

<customSection>
  <element name="A" />
  <element name="B" />
  <element name="C" />
<customSection>

Ответы

Ответ 1

Я предполагаю, что collection является свойством вашего пользовательского класса ConfigurationSection.

Вы можете украсить это свойство следующими атрибутами:

[ConfigurationProperty("", IsDefaultCollection = true)]
[ConfigurationCollection(typeof(MyElementCollection), AddItemName = "element")]

Полная реализация для вашего примера может выглядеть так:

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"]; }
    }
}

Теперь вы можете получить доступ к своим настройкам следующим образом:

var config = (MyCustomSection)ConfigurationManager.GetSection("customSection");

foreach (MyElement el in config.Elements)
{
    Console.WriteLine(el.Name);
}

Это позволит использовать следующий раздел конфигурации:

<customSection>
    <element name="A" />
    <element name="B" />
    <element name="C" />
<customSection>