Question

Concider the following config section:

<PluginSection>
    <Plugins>
       <Plugin name="Plug1">
          <add MessageType="1" MessageSubType="1" Ringtone="chime.wav" Vibrate="1000:0:1"/>
          <add MessageType="1" MessageSubType="2" Ringtone="chime2.wav" Vibrate="1000:0:1"/>
       </Plugin>
       <Plugin name="Plug2">
          <add MessageType="1" MessageSubType="1" Ringtone="chime.wav"/>
          <add MessageType="1" MessageSubType="2" Ringtone="chime2.wav"/>
          <add MessageType="2" Ringtone="chime3.wav"/>
       </Plugin>
    </Plugins>
 </PluginSection>

I've implemented the parsing of this as a c# IConfigSectionHandler. Now I understand that this method is deprecated, and that I should use ConfigurationSection, ConfigurationElements and ConfigurationElementCollections. I have no problem understanding the examples of this on the web (msdn and SO). But all the examples I've seen so far have used one of the properties as a key. My elements are unique as a combination of the Plugin name, MessageType and MessageSubType. The MessageSubType is also optional. Could i parse a config section that looks like this using the recommended classes, or do I have to alter my configuration to fit the regime of the ConfigurationClasses by e.g. adding a "dummy" key?

Was it helpful?

Solution

No.

But to avoid keys you need to do more work.

The concrete type KeyValueConfigurationCollection allows easy creation of a configuration collection by setting some properties.

To create a more customised collection requires either extending the abstract ConfigurationElementCollection (but this will still be based on the add/remove/clear model as used by <appSettings>. but allowing the element names to be configured but this is still based on ahaving a key value for each member of the collection (this is determined by an override of GetElementKey so does not need to be directly included in the XML).

Alternatively you can create you own, completely custom configuration collection by extending ConfigurationElement, but you'll need to do all the work of parsing the child elements yourself (remember ConfigurationElementCollection is itself a child class of ConfigurationElement).

OTHER TIPS

So based on the excelent answer from Richard, i decided to rewrite my config parsing. Heres the result:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;

namespace PluginConfiguration
{
    public class PluginConfigSection : ConfigurationSection
    {
        [ConfigurationProperty("Plugins", IsDefaultCollection = true)]
        [ConfigurationCollection(typeof(PluginCollection), AddItemName = "Plugin")]
        public PluginCollection Plugins
        {
            get
            {
                PluginCollection coll = (PluginCollection)base["Plugins"];
                return coll;
            }
        }
    }

    public class PluginCollection : ConfigurationElementCollection
    {

        protected override ConfigurationElement CreateNewElement()
        {
            return new MessageMappingElementCollection();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            MessageMappingElementCollection coll = element as MessageMappingElementCollection;
            return coll.Name;
        }
    }

    public class MessageMappingElementCollection : ConfigurationElementCollection
    {
        [ConfigurationProperty("name", IsRequired = true, IsKey = true)]
        public string Name
        {
            get { return this["name"].ToString(); }
            set { this["name"] = value; }
        }

        protected override ConfigurationElement CreateNewElement()
        {
            return new MessageMappingElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            MessageMappingElement msgElement = element as MessageMappingElement;

            string ret = String.Format("{0}|{1}", msgElement.MessageType, msgElement.MessageSubType);
            return ret;
        }
    }

    public sealed class MessageMappingElement : ConfigurationElement
    {
        public MessageMappingElement()
        {
            MessageType = 0;
            MessageSubType = 0;
            RingTone = "";
            Description = "";
            Vibrate = "";
        }

        [ConfigurationProperty("MessageType", IsRequired = true)]
        public int MessageType
        {
            get { return int.Parse(this["MessageType"].ToString()); }
            set { this["MessageType"] = value; }
        }

        [ConfigurationProperty("MessageSubType", IsRequired = false)]
        public int MessageSubType
        {
            get { return int.Parse(this["MessageSubType"].ToString()); }
            set { this["MessageSubType"] = value; }
        }

        [ConfigurationProperty("RingTone", IsRequired = false)]
        public string RingTone
        {
            get { return this["RingTone"].ToString(); }
            set { this["RingTone"] = value; }
        }

        [ConfigurationProperty("Description", IsRequired = false)]
        public string Description
        {
            get { return this["Description"].ToString(); }
            set { this["Description"] = value; }
        }

        [ConfigurationProperty("Vibrate", IsRequired = false)]
        public string Vibrate
        {
            get { return this["Vibrate"].ToString(); }
            set { this["Vibrate"] = value; }
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top