User config section with a list

98 views Asked by At

I know that what I am trying to do is possible, because I have done it - I just no longer have access to the code that I did it in. What is more, I cannot find using Google the details for how to do it.

I have a config file containing something like the following:

<resources>
    <item title="A" details="aaaaaa" />
    <item title="b" details="bbbbbbb" />
    <item title="c" details="ccccc" />
    <item title="d" details="ddddd" />
</resources>

both the title and the details are (potentially) HTML.

I want to load these into my code through the handler defined to describe them, which is (basically)

public class ResourceGroup : ConfigurationSection, IConfigurationSectionHandler
{
    private ResourceGroup() {}
    public static List<ResourceDetail> getDetails()
    {
        var items = new List<ResourceDetail>();
        var entry= ConfigurationManager.GetSection("resources");
???
            items.Add(new ResourceDetail(node));
???            
        return items;
    }

I know that I can look through the entries in this config section in XML, adding resourceDetails entries created form the XML nodes. However I cannot find how to do it.

Alternatively, how do I represent this list of entries in config using the Property definitions. I would rather avoid using the "add" approach, because they don't have a key naturally.

Thank you.

Edit - config file config section:

<configSections>
    <section name="resources" type="BoredWithChurch.ConfigHandlers.ResourceGroup" />
    <section name="links" type="BoredWithChurch.ConfigHandlers.LinksHandler" />
</configSections>
1

There are 1 answers

1
huysentruitw On BEST ANSWER

As far as I see, there is no way to let ResourceGroup inherit from ConfigurationSection and ConfigurationElementCollection, which means you'll have to add an additional node that keeps the <item>'s together:

<resources>
    <items>
        <item title="A" details="aaaaaa" />
        <item title="b" details="bbbbbbb" />
        <item title="c" details="ccccc" />
        <item title="d" details="ddddd" />
    </items>
</resources>

Then the ResourceGroup class will look like this:

public class ResourceGroup : ConfigurationSection
{
    [ConfigurationProperty("items", IsRequired=true)]
    public ResourceItemCollection Items
    {
        get { return (ResourceItemCollection)this["items"]; }
    }
}

The ResourceItemCollection class:

[ConfigurationCollection(typeof(ResourceItem), AddItemName = "item", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class ResourceItemCollection : ConfigurationElementCollection
{
    public ResourceItem this[int index]
    {
        get { return (ResourceItem)BaseGet(index); }
    }

    public new ResourceItem this[string name]
    {
        get { return (ResourceItem)BaseGet(name); }
    }

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

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((ResourceItem)element).Title;
    }
}

And last but not least, the ResourceItem class:

public class ResourceItem : ConfigurationElement
{
    [ConfigurationProperty("title", IsRequired = true)]
    public string Title
    {
        get { return (string)this["title"]; }
    }
    [ConfigurationProperty("details", IsRequired = true)]
    public string Details
    {
        get { return (string)this["details"]; }
    }
}

Usage

static void Main(string[] args)
{
    var section = ConfigurationManager.GetSection("resources") as ResourceGroup;
    foreach (ResourceItem item in section.Items)
    {
        Console.WriteLine(item.Title);
    }
    Console.ReadKey();
}