Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use .NET custom ConfigurationElement properties on descendent elements?

How can I get and use an attribute set in the parent ConfigurationSection in the descendent CustomSetting element? I need this attribute when the CustomSetting element is returning the Value property.

I want to format the App.config like this:

<CustomSettings someProperty="foo">
    <CustomSetting key="bar" value="fermeneba" />
    <CustomSetting key="laa" value="jubaduba" />
</CustomSettings>

I have the code working, except that I cannot find a way to access the someProperty attribute from the CustomSetting class. The only way that I've found, so far, is to format the configuration like this, which is messy:

<CustomSettings>
    <CustomSetting someProperty="foo" key="bar" value="fermeneba" />
    <CustomSetting someProperty="foo" key="laa" value="jubaduba" />
</CustomSettings>
like image 282
Jeremy Gaither Avatar asked Aug 12 '11 18:08

Jeremy Gaither


1 Answers

Achieving this is more difficult than it should be since the System.Configuration API doesn't allow you to navigate from a ConfigurationElement to its parent. Hence, if you want to access some information that on a parent element you need to create that relationship manually. I've put together a sample implementation that does that for the config snippet in your question:

public class CustomSettingsSection : ConfigurationSection
{
    [ConfigurationProperty("someProperty", DefaultValue="")]
    public string SomeProperty
    {
        get { return (string)base["someProperty"]; }
        set { base["someProperty"] = value; }
    }

    [ConfigurationProperty("", IsDefaultCollection = true)]
    public CustomSettingElementCollection Elements
    {
        get 
        {
            var elements = base[""] as CustomSettingElementCollection;
            if (elements != null && elements.Section == null)
                elements.Section = this;
            return elements;
        }
    }
}

public class CustomSettingElementCollection : ConfigurationElementCollection
{

    internal CustomSettingsSection Section { get; set; }

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

    public CustomSettingElement this[string key]
    {
        get { return BaseGet(key) as CustomSettingElement; }
    }

    protected override ConfigurationElement CreateNewElement()
    {
        return new CustomSettingElement { Parent = this };
    }

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

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

public class CustomSettingElement : ConfigurationElement
{

    internal CustomSettingElementCollection Parent { get; set; }

    public string SomeProperty
    {
        get
        {
            if (Parent != null && Parent.Section != null)
                return Parent.Section.SomeProperty;
            return default(string);
        }
    }




    [ConfigurationProperty("key", IsKey = true, IsRequired = true)]
    public string Key
    {
        get { return (string)base["key"]; }
        set { base["key"] = value; }
    }

    [ConfigurationProperty("value", DefaultValue = "")]
    public string Value
    {
        get { return (string)base["value"]; }
        set { base["value"] = value; }
    }

}

You can see that the CustomSettingElementCollection has a Section property which gets set in the section's Elements getter. The CustomSettingElement, in turn, has a Parent property which gets set in the collection's CreateNewElement() method.

That then makes it possible to walk up the relationship tree and to add a SomeProperty property to the element even though this one doesn't correspond to an actual ConfigurationProperty on that element.

Hope that gives you an idea how to solve your problem!

like image 132
mthierba Avatar answered Sep 19 '22 23:09

mthierba