Custom configuration properties - Entry has already been added

761 Views Asked by At

I'm developing a windows service that reads information from the app.config at start-up which should allow us to change internal thread configuration without redeploying the service.

I created some custom configuration sections and elements as follows (implementation omitted):

public class MyConfigurationSection
{
    [ConfigurationProperty("threads")]
    [ConfigurationCollection(typeof(MyThreadCollection), AddItemName="addThread")>
    public MyThreadCollection threads { get; }
}

public class MyThreadCollection
{
    protected override void CreateNewElement();
    protected override object GetElementKey(ConfigurationElement element);
}

public class MyThreadElement
{
    [ConfigurationProperty("active", DefaultValue=true, IsRequired=false)>
    public bool active { get; set; }

    [ConfigurationProperty("batchSize", DefaultValue=10, IsRequired=false)>
    public int batchSize { get; set; }

    [ConfigurationProperty("system", IsRequired=true)>
    public string system { get; set; }

    [ConfigurationProperty("department", IsRequired=true)>
    public string department { get; set; }

    [ConfigurationProperty("connection", IsRequired=true)>
    public MyThreadConnectionElement connection { get; set; }
}

public class MyThreadConnectionElement
{
    [ConfigurationProperty("server", IsRequired=true)>
    public string server { get; set; }

    [ConfigurationProperty("database", IsRequired=true)>
    public string database { get; set; }

    [ConfigurationProperty("timeout", DefaultValue=15, IsRequired=false)>
    public int timeout { get; set; }
}

Then I add some elements to the app.config as follows:

<configurationSection>
    <threads>
        <addThread
            active="True"
            batchSize="50"
            system="MySystem1"
            department="Department1">
            <connectionString
                server="MyServer"
                database="Database1" />
        </addThread>
        <addThread
            active="True"
            batchSize="30"
            system="MySystem2"
            department="Department2">
            <connectionString
                server="MyServer"
                database="Database2" />
        </addThread>
    </threads>
</configurationSection>

Everything works - configuration is read, threads are created, and the processes run.

The problem is, I would like both these threads to have the same system name/value -- both should be MySystem -- but when I do that and run the program, I get a The entry 'MySystem' has already been added. exception.

I figured it might be because a property has to be explicitly configured to allow duplicates, but I don't know how and I couldn't find a property of the ConfigurationProperty class that might allow that, other than IsKey, but from its description it didn't seem like the answer, and trying it didn't solve the problem. Am I on the right track here?

Initially the system property was named name and I though that just maybe any property named name is treated as a unique identifier, so I changed it to system but it didn't change anything.

I tried the <clear /> tag as some other, similar posts suggested, without success.

Do I need to add another hierarchy to the configuration section -- Config -> Department -> Thread instead of Config -> Thread? I'd prefer to not take this approach.

Thanks for any and all input.

1

There are 1 best solutions below

0
On BEST ANSWER

I actually found the problem and solution quite some time ago, but forgot to post the answer; thanks @tote for reminding me.

When implementing the ConfigurationElementCollection class, the GetElementKey(ConfigurationElement) method can be overridden. Without immediately realising what the method is for I overrode it and simply returned the system property value, and, since more than one configuration element had the same system name, technically they had the same key, which is why the error occurred.

The solution for me was to return the system and the department values as system.department which resulted in unique keys.