Вложенные пользовательские элементы в app.config (C #)

#c# #xml #nested #app-config

#c# #xml #вложенные #app-config

Вопрос:

Спасибо всем,

В течение нескольких часов я пытался понять, как считывать настройки из файла app.config:

 <?xml version="1.0"?>
<configuration>

  <configSections>
    <section name="Databases" type="McFix.DatabaseSection, McFix"/>
  </configSections>

  <Databases>
    <Database name="database">
      <Tables>
        <Table name="be_sessions">
          <Columns>
            <Column name="sess_id">
            </Column>
          </Columns>
        </Table>
      </Tables>
    </Database>
  </Databases>

  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
</configuration>
  

Код для пользовательских классов обработчиков находится здесь, также скопирован ниже:

 public class DatabaseSection : ConfigurationSection
{
    [ConfigurationProperty("Databases", IsDefaultCollection = false)]
    public DatabaseInstanceCollection Databases
    {
        get { return (DatabaseInstanceCollection)this["Databases"]; }
        set { this[""] = value; }
    }
}
[ConfigurationCollection(typeof(DatabaseElement), AddItemName = "add", CollectionType = ConfigurationElementCollectionType.BasicMap )]
public class DatabaseInstanceCollection : ConfigurationElementCollection
{
    protected override ConfigurationElement CreateNewElement()
    {
        return new DatabaseElement();
    }
    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((DatabaseElement)element).Name;
    }
}
public class DatabaseElement : ConfigurationElement
{
    [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
    public string Name
    {
        get { return (string)base["name"]; }
        set { base["name"] = value; }
    }
}

public class TableSection : ConfigurationSection
{
    [ConfigurationProperty("Tables", IsDefaultCollection = true)]
    public TableInstanceCollection Tables
    {
        get { return (TableInstanceCollection)this["Tables"]; }
        set { this[""] = value; }
    }
}

[ConfigurationCollection(typeof(TableElement), AddItemName = "Table", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class TableInstanceCollection : ConfigurationElementCollection
{
    protected override ConfigurationElement CreateNewElement()
    {
        return new TableElement();
    }
    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((TableElement)element).Name;
    }
}

public class TableElement : ConfigurationElement
{
    [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
    public string Name
    {
        get { return (string)base["name"]; }
        set { base["name"] = value; }
    }
}

public class ColumnSection : ConfigurationSection
{
    [ConfigurationProperty("Columns", IsDefaultCollection = true)]
    public ColumnInstanceCollection Columns
    {
        get { return (ColumnInstanceCollection)this["Columns"]; }
        set { this[""] = value; }
    }
}

[ConfigurationCollection(typeof(ColumnElement), AddItemName = "Column", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class ColumnInstanceCollection : ConfigurationElementCollection
{
    protected override ConfigurationElement CreateNewElement()
    {
        return new ColumnElement();
    }
    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((ColumnElement)element).Name;
    }
}

public class ColumnElement : ConfigurationElement
{
    [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
    public string Name
    {
        get { return (string)base["name"]; }
        set { base["name"] = value; }
    }
}
  

Проблема заключается в том, когда я пытаюсь получить раздел «Базы данных» с помощью метода GetSection:

 Configuration Config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
DatabaseSection DbConfig = Config.GetSection("Databases") as DatabaseSection;
  

программа выдает исключение ConfigurationErrorsException, сообщающее о «Нераспознанном элементе ‘Database'», хотя это происходит после прохождения метода get DatabaseSection, хотя я определяю AddItemName для DatabaseInstanceCollection как «База данных». Я что-то упускаю, атрибут, который позволит базовому коду правильно прочитать app.config?

Комментарии:

1. Что не так с форматированием SO? Кроме того, для этого вам нужно будет проделать дополнительную работу. Опишите, что у вас не сработало и в чем ваша проблема. Никто не собирается читать ваш код, чтобы выяснить, что пошло не так. Приведите примеры ваших сбоев.

2. Вы спрашиваете, как читать в настройках конфигурации, используя определенные вами классы? Я не видел ничего в вашем коде, где вы на самом деле это читали.

3. Если вы хотите опубликовать образцы кода, XML или данных , выделите эти строки в текстовом редакторе и нажмите на кнопку «образцы кода» ( { } ) на панели инструментов редактора, чтобы красиво оформить и выделить синтаксис! SO будет довольно красиво форматировать и отображать его, если вы это сделаете!

4. Приношу всем свои извинения за то, что некоторое время не размещал вопросы на форумах (в основном потому, что отвечал на вопросы других), я потерял контакт.

Ответ №1:

Обязательные ссылки:

После беглого просмотра кажется, что ваша проблема в этой строке:

 [ConfigurationCollection(typeof(DatabaseElement), AddItemName = "add", CollectionType = ConfigurationElementCollectionType.BasicMap )]
  

Это указывает на то, что файл .config должен выглядеть следующим образом:

 <Databases>
    <add><!-- Database goes here --></add>
</Databases>
  

Т.е. ваш Databases элемент ожидает дочернего элемента «добавить», чтобы указать, что элемент должен быть добавлен в коллекцию.

Вам следует попробовать изменить AddItemName свойство с «добавить» на «База данных»:

 [ConfigurationCollection(typeof(DatabaseElement), AddItemName = "Database", CollectionType = ConfigurationElementCollectionType.BasicMap )]
  

(У меня не было возможности протестировать это, могут быть другие проблемы)

Комментарии:

1. Спасибо, Краген, я просмотрел вопросы и ответы по поводу аналогичной конфигурации приложения для . NET здесь и посещенные ссылки, о которых вы упоминали ранее, но, увы. Я попытался изменить AddItemName на «Database», но тоже безрезультатно. У меня есть подозрение, что элемент «Database» должен быть объявлен для раздела «Базы данных», хотя я бы подумал, что это делается через свойство «AddItemName» атрибута ConfigurationCollection.

2. @user696034 Влияет ли это на сообщение об ошибке? Я также заметил, что DatabaseElement элемент configuration не имеет ссылки на TableSection раздел configuration, и поэтому я ожидаю, что это, вероятно, приведет к сбою даже после устранения вышеуказанного.

3. Мне удалось запустить все это, но ты прав, Краген, было необходимо добавить TableInstanceCollection в DatabaseElement и ColumnInstanceCollection в TableElement. Кроме того, раздел DatabaseSection должен был быть выполнен таким образом, чтобы работать:

Ответ №2:

Ты прав, Краген, мне пришлось удалить Table / ColumnSection и добавить Table / ColumnInstanceCollection в Database / TableElement. Свойство DatabaseSection’Databases должно было быть похоже:

 [ConfigurationProperty("", IsDefaultCollection = true)]
        public DatabaseInstanceCollection Databases
        {
            get { return (DatabaseInstanceCollection)this[""]; }
        }