views:

192

answers:

1

I have designed a custom section handler before but I'm faced with a problem that I can not seem to think up. I have a configuration section like this:

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"&gt;
    <configSections>
     <section name="providers" requirePermission="false" type="MyProject.Configuration.ProvidersSection"/>
    </configSections>

    <providers>
     <provider name="products">
      <queries>
       <add name="insert" value="InsertProduct" />
       <add name="retrieve" value="GetProduct" />
       <add name="collect" value="GetProducts" />
       <add name="update" value="UpdateProduct" />
       <add name="delete" value="DeleteProduct" />
      <queries>
     </provider>
     <provider name="tasks">
      <queries>
       <add name="insert" value="InsertTask" />
       <add name="retrieve" value="GetTaskById" />
       <add name="collect" value="GetMultipleTasks" />
       <add name="update" value="UpdateTask" />
       <add name="delete" value="DeleteTask" />
      <queries>
     </provider>
     <provider name="events">
      <queries>
       <add name="insert" value="AddEvent" />
       <add name="retrieve" value="GetEvent" />
       <add name="collect" value="GetEvents" />
       <add name="update" value="UpdateEvent" />
       <add name="delete" value="DeleteEvent" />
      <queries>
     </provider>
    </providers>
</configuration>

I created the following handler classes:

using System.Configuration;

namespace MyProject.Configuration
{
    public class ProvidersSection : ConfigurationSection
    {
        public new Element this[string key]
        {
            get
            {

            }
        }
    }

    [ConfigurationCollection(typeof(ProviderElement))]
    public class ProvidersCollection : ConfigurationElementCollection
    {

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

        protected override object GetElementKey(ConfigurationElement element)
        {
            return element.ElementInformation.Properties["name"].Value;
        }

        public ProviderElement this[string key]
        {
            get
            {
                return (ProviderElement)base.BaseGet(key);
            }
        }
    }

    public class ProviderElement : ConfigurationElement
    {
        public string this[string name]
        {
            get
            {
                return string.Empty;
            }
        }
    }
}

What code do I need in these classes in order to successfully execute the following code?

string query = ProvidersSection["tasks"].Queries["Insert"];
+2  A: 

You should look into using ConfigurationElementCollection and KeyValueConfigurationCollection for the Elements you want to use as a collection. In this case, you will have to make a collection of elements, each element having a KeyValueConfigurationCollection. So, instead of the XML config that you have above, you will have something more like this:

<providers>
    <provider key="products">
        <queries>
             <add key="whatever" value="stuff" />
             ...etc...
        <queries>
    <provider>
</providers>

You can re-use the "queries" element, which will be your KeyValueConfigurationCollection, for each "provider."

A quick Google search yielded this article on MSDN, which also may be of help.

Edit - code example

Your root section definition will be like this:

public class ProviderConfiguration : ConfigurationSection
{
    [ConfigurationProperty("Providers",IsRequired = true)]
    public ProviderElementCollection Providers
    {
        get{ return (ProviderElementCollection)this["Providers"]; }
        set{ this["Providers"] = value; }
    }
}

Then, your Providers ElementCollection:

public class ProviderCollection : ConfigurationElementCollection
{
    public ProviderElement this[object elementKey]
    {
        get { return BaseGet(elementKey); }
    }

    public void Add(ProviderElement provider)
    {
        base.BaseAdd(provider);
    }

    public override ConfigurationElementCollectionType CollectionType
    {
        get { return ConfigurationElementCollectionType.BasicMap; }
    }

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

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((ProviderElement)element).Key;
    }

    protected override string ElementName
    {
        get { return "Provider"; }
    }
}

Then, your Provider element:

public class Provider : ConfigurationElement
{
    [ConfigurationProperty("Key",IsRequired = true, IsKey = true)]
    public string Key
    {
        get { return (string) this["Key"]; }
        set { this["Key"] = value; }
    }

    [ConfigurationProperty("Queries", IsRequired = true)]
    public KeyValueConfigurationCollection Queries
    {
        get { return (KeyValueConfigurationCollection)this["Queries"]; }
        set { this["Queries"] = value; }
    }
}

You're probably going to have to mess around with the KeyValueConfigurationCollection a bit to make it work right, but I think this would be the general idea. Then, when accessing this stuff in your code, you would do something like this:

var myConfig = (ProviderConfiguration)ConfigurationManager.GetSection("Providers");
//and to access a single value from, say, your products collection...
var myValue = myConfig.Providers["Products"].Queries["KeyForKeyValuePairing"].Value;

Hope that helps. Now just don't ask me to translate it to VB :-D

AJ
Thank you for your prompt response. I greatly appreciate your efficient approach. I managed to figure out how to handle the collections within a single provider. However, how can I make my "ProvidersSection" class a SectionHandler as well as a ConfigurationElementCollection?
deverop
I guess another way to ask this question is, "How can I create a collection of ConfigurationElementCollection objects mapping to each provider within the SectionHandler?
deverop
Edited my answer with code.
AJ
Excellent! I give 5 stars ****Thank You.
deverop