Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple custom config section with collection in .NET4

I'm trying to write a very simple custom configuration section for a .NET4 application. My goal is this:

<configuration>
  <configSections>
    <section name="myServices" type="My.ConfigSection, My.Assembly" />
  </configSections>
  <myServices>
    <add name="First" />
    <add name="Second" />
  </myServices>
</configuration>

However, I keep getting a ConfigurationErrorsException: 'Unrecognized element 'add'' when I call ConfigurationManager.GetSection("myServices"). I've been staring at it for a while now but haven't figured out yet what I'm doing wrong. Below is my code. It's three classes: ConfigSection, MyServiceSettingsCollection and MyServiceSettings.

First the class that represents the entire config section. It has a nameless default collection of type MyServiceSettingsCollection. The IsDefaultCollection property should allow me to 'add' directly to my collection from the root element.

public sealed class ConfigSection : ConfigurationSection
{
  private static readonly ConfigurationProperty _propMyServices;

  private static readonly ConfigurationPropertyCollection _properties;

  public static ConfigSection Instance { get { return _instance; } }

  static ConfigSection()
  {
    _propMyServices = new ConfigurationProperty(
          null, typeof(MyServiceSettingsCollection), null,
          ConfigurationPropertyOptions.IsDefaultCollection);
    _properties = new ConfigurationPropertyCollection { _propMyServices };
  }

  [ConfigurationProperty("", IsDefaultCollection = true)]
  public MyServiceSettingsCollection MyServices
  {
    get { return (MyServiceSettingsCollection) base[_propMyServices]; }
    set { base[_propMyServices] = value; }
  }

  protected override ConfigurationPropertyCollection Properties
  { get { return _properties; } }
}

Next, the collection class itself. It is of type AddRemoveClearMap.

[ConfigurationCollection(typeof(MyServiceSettings),
    CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
public sealed class MyServiceSettingsCollection : ConfigurationElementCollection
{
  public MyServiceSettings this[int index]
  {
    get { return (MyServiceSettings) BaseGet(index); }
    set
    {
      if (BaseGet(index) != null) { BaseRemoveAt(index); }
      BaseAdd(index, value);
    }
  }

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

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

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

And finally a class for the elements in the collection. For now, this class has one property but there will be more later (which prevents me from using NameValueSectionHandler).

public class MyServiceSettings : ConfigurationElement
{
  private static readonly ConfigurationProperty _propName;

  private static readonly ConfigurationPropertyCollection properties;

  static MyServiceSettings()
  {
    _propName = new ConfigurationProperty("name", typeof(string), null, null,
                                          new StringValidator(1),
                                          ConfigurationPropertyOptions.IsRequired |
                                          ConfigurationPropertyOptions.IsKey);
    properties = new ConfigurationPropertyCollection { _propName };
  }

  [ConfigurationProperty("name", DefaultValue = "",
        Options = ConfigurationPropertyOptions.IsRequired |
                  ConfigurationPropertyOptions.IsKey)]
  public string Name
  {
      get { return (string) base[_propKey]; }
      set { base[_propKey] = value; }
  }

  protected override ConfigurationPropertyCollection Properties
  { get { return properties; } }
}
like image 294
Ronald Wildenberg Avatar asked Aug 15 '11 14:08

Ronald Wildenberg


People also ask

How do I add a config section in app config?

We will start with creating an class that can store the instance settings (the <add> element), then we'll create a collection that can store our instances (the <instances> element) and then we'll create the class to manage the Configuration Section (the <sageCRM> element).

What is config section in web config?

config file includes settings that apply to all of the ASP.NET applications that run a specific version of the . NET Framework. Because each ASP.NET application inherits default configuration settings from the root Web.


1 Answers

Ok, I found the seemingly random fix. Instead of this:

[ConfigurationProperty("", IsDefaultCollection = true)]
public ProvisiorServiceSettingsCollection ProvisiorServices
{ ... }

you should use:

[ConfigurationProperty("", Options = ConfigurationPropertyOptions.IsDefaultCollection)]
public ProvisiorServiceSettingsCollection ProvisiorServices
{ ... }

No idea what the difference is between the two. To me, they look strikingly similar... or at least, there is no suggestion anywhere why one is preferred over the other.

like image 127
Ronald Wildenberg Avatar answered Sep 23 '22 08:09

Ronald Wildenberg