C# – Custom Configuration, ConfigurationElements, and ConfigurationProperties

app-configc++configurationelementconfigurationsection

I've been scouring the net for the last 3 days, and can't find any reference to this question. I've created a custom configuration class to be used with my app.config. Everything works fine. The problem comes in when a configuration property (of a configuration element) is not required, and is not defined in the app.config. It seems that default values are returned for the configuration property. Does anyone know how to determine if the property isn't defined in the app.config? (I've been trying to post my app.config, but can't figure out how to do it…anyone know how?)


//Main
namespace TestStub
{
    class Program
    {
        static void Main(string[] args)
        {
            CustomSettingsHandler config = (CustomSettingsHandler)ConfigurationManager.GetSection("CustomSettingsManager");
            Console.WriteLine("Setting1 {0}", config.Setting1.CustomSettingItem);
            Console.WriteLine("Setting2 {0}", config.Setting2.CustomSettingItem);
        }
    }
}

//Custom Configuration Class
namespace CustomConfiguration
{
    public class CustomSettingsHandler : ConfigurationSection
    {
        [ConfigurationProperty("setting1", IsRequired = false)]
        public CustomSettingElement Setting1 { get { return (CustomSettingElement)this["setting1"]; } }

        [ConfigurationProperty("setting2", IsRequired = false)]
        public CustomSettingElement Setting2 { get { return (CustomSettingElement)this["setting2"]; } }
    }

    public class CustomSettingElement : ConfigurationElement
    {
        [ConfigurationProperty("customsettingitem", IsRequired = false)]
        public int CustomSettingItem { get { return (int)this["customsettingitem"]; } }
    }
}

Best Solution

I found the best way is to override ConfigurationSection.PostDeserialize() and check the IsPresent property of each section member that derives from ConfigurationElement.

public class CustomSettingsHandler : ConfigurationSection
{
    // ...

    protected override void PostDeserialize()
    {
        foreach (ConfigurationProperty property in Properties)
        {
            var configElement = this[property] as ConfigurationElement;

            if (configElement != null 
                && !configElement.ElementInformation.IsPresent)
            {
                this[property] = null;
            }
        }

        base.PostDeserialize();
    }
}

Each ConfigurationElement that has not been read from the config file will be null afterwards.