Question

I'm in the process of attempting to remove some old legacy references and I'm now working on something I've never had to try doing before. Let's say I have a config file section like this:

<customSection>
    <customValues>
      <custom key="foo" invert="True">
         <value>100</value>
      </custom>
      <custom key="bar" invert="False">
         <value>200</value>
      </custom>
    </customValues>
</customSection>

I've now created ConfigurationSection, ConfigurationElement, and ConfigurationElementCollection classes to correctly read all of this out. Here they are for reference (it's basically all boiler plate except for the ValueElement class which overrides the Deserialize method to get at the element's value):

public class CustomSection : ConfigurationSection
{
    [ConfigurationProperty("customValues")]
    [ConfigurationCollection(typeof(CustomValueCollection), AddItemName = "custom")]
    public CustomValueCollection CustomValues
    {
        get { return (CustomValueCollection)this["customValues"]; }
    }
}

public class CustomValueCollection : ConfigurationElementCollection
{
    protected override ConfigurationElement CreateNewElement()
    {
        return new CustomElement();
    }

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

    public CustomElement this[int index]
    {
        get { return (CustomElement) BaseGet(index); }
    }

    new public CustomElement this[string key]
    {
        get { return (CustomElement) BaseGet(key); }
    }

    public bool ContainsKey(string key)
    {
        var keys = new List<object>(BaseGetAllKeys());
        return keys.Contains(key);
    }
}

public class CustomElement : ConfigurationElement
{
    [ConfigurationProperty("key", IsRequired = true)]
    public string Key
    {
        get { return (string)this["key"]; }
    }

    [ConfigurationProperty("invert", IsRequired = true)]
    public bool Invert
    {
        get { return (bool)this["invert"]; }
    }

    [ConfigurationProperty("value", IsRequired = true)]
    public ValueElement Value
    {
        get { return (ValueElement)this["value"]; }
    }
}

public class ValueElement : ConfigurationElement
{
    private int value;

    //used to get value of element, not of an attribute
    protected override void DeserializeElement(System.Xml.XmlReader reader, bool serializeCollectionKey)
    {
        value = (int)reader.ReadElementContentAs(typeof(int), null);
    }

    public int Value
    {
        get { return value; }
    }
}

What I'm now stuck on is this business requirement: if a CustomElement has an Invert value of true, then invert the value of the Value property in the associated ValueElement. So if I accessed the value of "value" under "foo", I would get -100.

Does anyone have any idea how to either pass something like that in to the ValueElement object or make the ValueElement aware of its parent CustomElement to be able to get at that Invert property? My initial thought is to do the check in the Value property getter of the CustomElement class, and if Invert is true, then modify the ValueElement object there, but I'm open to other ideas.

The goal here is to remove the legacy code without touching the config file, otherwise I'd push the "value" subelement up into the parent as an attribute.

Thanks

Was it helpful?

Solution

By the look of it, you just need to modify the Value property getter to include your invert logic. I can see no reason why that wouldn't work.

You could add another property that gets the raw value as well.

[ConfigurationProperty("value", IsRequired = true)]
public int Value
{
    get 
    {
        var result = (ValueElement)this["value"]; 
        return Invert ? result.Value * -1 : result.Value;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top