I'm actually astonished at the amount of time i spent trying to fix this and got absolutely nowhere in the end. I have the following app.config file i'm trying to read:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="BattleCity.Configuration" type="BattleCity.Configuration.GameConfiguration, BattleCity"/>
</configSections>
<BattleCity.Configuration>
<environment>
<add blockType="Test1"/>
<add blockType="Test2"/>
</environment>
</BattleCity.Configuration>
</configuration>
And here is the code for it:
#region Using Directives
using System;
using System.Configuration;
#endregion
namespace BattleCity.Configuration
{
public class GameConfiguration : ConfigurationSection
{
#region Public Members
/// <summary>
/// Retrieves an instance of the <see cref="GameConfiguration"/> with the
/// values populated from the App.config file.
/// </summary>
/// <returns>An <see cref="GameConfiguration" /> instance.</returns>
public static GameConfiguration GetConfig()
{
return ConfigurationManager.GetSection("BattleCity.Configuration") as GameConfiguration;
}
/// <summary>
/// A <see cref="GameConfigurationDimensions"/> instance.
/// </summary>
[ConfigurationProperty("dimensions", IsRequired = true)]
public GameConfigurationDimensions Dimensions
{
get
{
return this["dimensions"] as GameConfigurationDimensions;
}
}
/// <summary>
/// A <see cref="GameConfigurationElementCollection"/> instance that provides access
/// to a set of <see cref="GameConfigurationEnvironment"/>s.
/// </summary>
[ConfigurationProperty("environment", IsDefaultCollection = true, IsRequired = true)]
public GameConfigurationElementCollection<GameConfigurationEnvironment> Environment
{
get
{
return this["environment"] as GameConfigurationElementCollection<GameConfigurationEnvironment>;
}
}
#endregion
}
}
GameConfigurationDimensions.cs
#region Using Directives
using System;
using System.Configuration;
#endregion
namespace BattleCity.Configuration
{
public class GameConfigurationDimensions : ConfigurationElement
{
public GameConfigurationDimensions()
{ }
#region Properties
/// <summary>
/// Gets map height value.
/// </summary>
[ConfigurationProperty("mapHeight", IsRequired = true)]
public int MapHeight
{
get
{
return (int)this["mapHeight"];
}
}
/// <summary>
/// Gets map width value.
/// </summary>
[ConfigurationProperty("mapWidth", IsRequired = true)]
public int MapWidth
{
get
{
return (int)this["mapWidth"];
}
}
/// <summary>
/// Gets block pixel size value.
/// </summary>
[ConfigurationProperty("blockPixelSize", IsRequired = true)]
public int BlockPixelSize
{
get
{
return (int)this["blockPixelSize"];
}
}
/// <summary>
/// Gets number of blocks per row.
/// </summary>
[ConfigurationProperty("blocksPerRow", IsRequired = true)]
public int BlocksPerRow
{
get
{
return (int)this["blocksPerRow"];
}
}
#endregion
}
}
GameConfigurationElementCollection.cs
#region Using Directives
using System;
using System.Configuration;
using System.Collections.Generic;
#endregion
namespace BattleCity.Configuration
{
/// <summary>
/// Defines generic configuration element collection of the App.config file.
/// </summary>
/// <typeparam name="TYPE">Collection element type, which is either
/// <see cref="GameConfigurationDimensions"/> or
/// <see cref="GameConfigurationEnvironment"/>
/// </typeparam>
[Serializable()]
public class GameConfigurationElementCollection<TYPE> : ConfigurationElementCollection, IEnumerable<TYPE> where TYPE : ConfigurationElement, new()
{
#region Protected Members
/// <summary>
/// See <see cref="ConfigurationElementCollection.CreateNewElement()"/> for more information.
/// </summary>
protected override ConfigurationElement CreateNewElement()
{
return new TYPE();
}
/// <summary>
/// See <see cref="ConfigurationElementCollection.GetElementKey"/> for more information.
/// </summary>
protected override object GetElementKey(ConfigurationElement element)
{
return ((TYPE)element).GetType();
}
#endregion
#region Public Members
/// <summary>
/// See <see cref="IEnumerable{T}.GetEnumerator"/> for more information.
/// </summary>
public new IEnumerator<TYPE> GetEnumerator()
{
int count = base.Count;
for (int i = 0; i < count; i++)
{
yield return (TYPE)base.BaseGet(i);
}
}
/// <summary>
/// Adds a new element to the collection.
/// </summary>
/// <param name="element">The element to be added.</param>
public void Add(TYPE element)
{
base.BaseAdd(element);
}
#endregion
#region Indexers
/// <summary>
/// Gets or sets a configuration element of generic type at a specified ordinal index.
/// </summary>
public TYPE this[int index]
{
get
{
return base.BaseGet(index) as TYPE;
}
set
{
if (base.BaseGet(index) != null)
{
base.BaseRemoveAt(index);
}
this.BaseAdd(index, value);
}
}
#endregion
}
}
GameConfigurationEnvironment.cs
#region Using Directives
using System;
using System.Configuration;
#endregion
namespace BattleCity.Configuration
{
public class GameConfigurationEnvironment : ConfigurationElement
{
#region Properties
/// <summary>
/// Gets block type value.
/// </summary>
[ConfigurationProperty("blockType", IsRequired = true)]
public string BlockType
{
get
{
return (string)this["blockType"];
}
}
#endregion
}
}
The exception i am getting is
The entry 'BattleCity.Configuration.GameConfigurationEnvironment' has already been added.
which happens when it tries to read the second <add> tag. Could someone PLEASE tell me what the heck i'm doing wrong before i shoot myself over this.
Thank you.