0

I am trying to create a custom configuration section that represents the following xml structure:

<observerSettings>
   <jobSettings>
      <filter key="location" value="de">
        <filter key="type" value="MyType1">
          <filter key="status" value="failed">
            <actions>
              <notify timespan="12.00:00:00">
                <mailSettings>
                  <mailAddress to="mail1@something.com" />
                  <mailAddress to="mail2@something.com" />
                </mailSettings>
              </notify>
              <remove timespan="14.00:00:00">
                <mailSettings>
                  <mailAddress to="mail1@something.com" />
                  <mailAddress to="mail2@something.com" />
                </mailSettings>
              </remove>
            </actions> 
          </filter>
        </filter>
      </filter>
   </jobSettings>
</observerSettings>

The FilterConfigElement is defined like this:

internal class FilterConfigElement : ConfigurationElement, IFilterConfigElement
{
        [ConfigurationProperty("filter", IsRequired = false)]
        public FilterConfigElement ChildFilter => base["filter"] as FilterConfigElement;

        [ConfigurationProperty("actions", IsRequired = false)]
        public ActionsConfigElement Actions => base["actions"] as ActionsConfigElement;

        [ConfigurationProperty("key", IsRequired = true)]
        public string Key => base["key"] as string;

        [ConfigurationProperty("value", IsRequired = false)]
        public string Value => base["value"] as string;
}

When accessing the config section like below, the application is crashing with a StackOverflow exception:

internal class ObserverSettings : ConfigurationSection, IObserverSettings
{
   public static IObserverSettings Instance { get; private set; } = ConfigurationManager.GetSection("observerSettings") as ObserverSettings;

   [ConfigurationProperty("jobSettings")]
   protected JobSettingsCollection JobSettingsCollection => base["jobSettings"] as JobSettingsCollection;

   public virtual IJobSettingsCollection JobSettings => JobSettingsCollection;
}

So I assume ConfigurationManager is creating this structure with infinite depth and not stopping when the last filter element is reached. Can this be limited somehow? Is such structure even supported?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Matthias
  • 280
  • 2
  • 9
  • 19

1 Answers1

0

Ok, after digging through the implementation of ConfigurationElement it seems to be not possible at all to create recursive structures the way I tried.

Cause of the problem is the implementation of PropertiesFromType where assignment of the properties to s_propertyBags is done after the call to CreatePropertyBagFromType and thus creating an endless recursion where properties is always null.

private static bool PropertiesFromType(Type type, out ConfigurationPropertyCollection result)
{
   ConfigurationPropertyCollection properties = (ConfigurationPropertyCollection)s_propertyBags[type];
   result = null;
   bool firstTimeInit = false;
   if (properties == null) /*code omitted*/
   {
      properties = CreatePropertyBagFromType(type);
      s_propertyBags[type] = properties;
      firstTimeInit = true;
   }
   result = properties;
   return firstTimeInit;
}

Source: https://referencesource.microsoft.com/#System.Configuration/System/Configuration/ConfigurationElement.cs

Edit:

Only workaround to keep some kind of "recursive" structure was to wrap all child FilterConfigElements into a ConfigurationElementCollection with element name childFilter. This leads to following not so nice but acceptable config structure:

<jobSettings>
  <filter key="location" value="de">
    <childFilter>
      <filter key="type" value="MyType1">
        <childFilter>
          <filter key="status" value="failed">
            <actions>
              <!-- ... -->
            </actions>
          </filter>
        </childFilter>
      </filter>
    </childFilter>
  </filter>
</jobSettings>

Source: Recursive Custom Configuration in c#

Matthias
  • 280
  • 2
  • 9
  • 19