Search code examples
c#linqconfigurationconfigurationmanager

Custom config section with non-ConfigurationElement properties


I have a working custom configuration section. However, it is a pain to get at my data via a ConfigurationElementCollection but when I try to implement my property as an IEnumerable, it fails with the error:

ConfigurationErrorsException was unhandled "Property 'contacts' is not a ConfigurationElement."

Here is the code causing the failure:

[ConfigurationProperty("contacts", IsDefaultCollection = false)]
public IEnumerable<string> Contacts
{
    get { return ((ContactCollection)base["contacts"]).Cast<ContactElement>().Select(x => x.Address); }
}

However, if I change it to this:

[ConfigurationProperty("contacts", IsDefaultCollection = false)]
public ContactCollection Contacts
{
    get { return ((ContactCollection)base["contacts"]); }
}

Everything works fine. This answer makes it sound like this is just something Microsoft decided was not allowed and so I can't have any properties of types other than ConfigurationElement. Is this really the case? How can I implement my property as an IEnumerable<string>?

In case it matters, I'm trying to store emails and I'd like to have an element for each one since there may be a number of them, we may want to store more information on each contact in the future, and I think a single, comma-separated list might get ugly. For example, something like:

<emergency>
    <contact address="sirdank@stackoverflow.com" />
    <contact address="jon.skeet@stackoverflow.com" />
</emergency>

Or

<emergency>
    <contact>sirdank@stackoverflow.com</contact>
    <contact>jon.skeet@stackoverflow.com</contact>
</emergency>

Thanks!


Solution

  • Any harm in providing two methods? The first to fulfill the Microsoft requirement and the second to fulfill your own requirements.

        public IEnumerable<string> Contacts
        {
            get
            {
                return ContactCollection.Cast<ContactElement>().Select(x => x.Address);     
            }
        }
    
        [ConfigurationProperty("contacts", IsDefaultCollection = false)]
        public ContactCollection ContactCollection
        {
            get { return ((ContactCollection)base["contacts"]); }
        }