G'da to everyone,
For hours I've been trying to figure how to read settings from app.config file:
<?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>
The the code for custom handler classes is here, also copied below:
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; }
}
}
The problem is when I attempt to get "Databases" section via GetSection method:
Configuration Config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
DatabaseSection DbConfig = Config.GetSection("Databases") as DatabaseSection;
program throws an ConfigurationErrorsException, reporting "Unrecognized element 'Database'", although it does that after going through get method of DatabaseSection, even though I define AddItemName for DatabaseInstanceCollection as "Database". Am I missing something, attribute that will let underlying code read the app.config correctly?
Obligatory links:
After a cursory look it seems like your problem is on this line:
[ConfigurationCollection(typeof(DatabaseElement), AddItemName = "add", CollectionType = ConfigurationElementCollectionType.BasicMap )]
This indicates that the .config file should look like this:
<Databases>
<add><!-- Database goes here --></add>
</Databases>
I.e. your Databases
element is expecting an "add" child, to indicate that an item is to be added to the colleciton.
You should try changing the AddItemName
property from "add" to "Database":
[ConfigurationCollection(typeof(DatabaseElement), AddItemName = "Database", CollectionType = ConfigurationElementCollectionType.BasicMap )]
(I've not had a chance to test this, there may be other problems)
You're correct, Kragen, I had to remove Table/ColumnSection and add Table/ColumnInstanceCollection to Database/TableElement. DatabaseSection' Databases property had to be like:
[ConfigurationProperty("", IsDefaultCollection = true)]
public DatabaseInstanceCollection Databases
{
get { return (DatabaseInstanceCollection)this[""]; }
}
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