Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom app.config section with a simple list of "add" elements

Tags:

c#

app-config

How do I create a custom app.config section that is just a simple list of add elements?

I have found a few examples (e.g. How to create custom config section in app.config?) for custom sections that look like this:

<RegisterCompanies>
  <Companies>
    <Company name="Tata Motors" code="Tata"/>
    <Company name="Honda Motors" code="Honda"/>
  </Companies>
</RegisterCompanies>

But how do I avoid the extra collection element ("Companies") so that it looks the same as the appSettings and connectionStrings sections? In other words, I'd like:

<registerCompanies>
  <add name="Tata Motors" code="Tata"/>
  <add name="Honda Motors" code="Honda"/>
</registerCompanies>
like image 791
Joe Daley Avatar asked Apr 27 '10 01:04

Joe Daley


People also ask

How do I add a section in app config?

Open the App. config file and add the configSections, sectionGroup and section to it. We need to specify the name and fully qualified type of all the section and section group.

Can we add app config file in class library?

You generally should not add an app. config file to a class library project; it won't be used without some painful bending and twisting on your part. It doesn't hurt the library project at all - it just won't do anything at all.

Can we have multiple app config?

You cannot use multiple configuration files (i.e. one per library project) without coding.


4 Answers

Full example with code based on OP config file:

<configuration>
    <configSections>
        <section name="registerCompanies" 
                 type="My.MyConfigSection, My.Assembly" />
    </configSections>
    <registerCompanies>
        <add name="Tata Motors" code="Tata"/>
        <add name="Honda Motors" code="Honda"/>
    </registerCompanies>
</configuration>

Here is the sample code to implement a custom config section with collapsed collection

using System.Configuration;
namespace My {
public class MyConfigSection : ConfigurationSection {
    [ConfigurationProperty("", IsRequired = true, IsDefaultCollection = true)]
    public MyConfigInstanceCollection Instances {
        get { return (MyConfigInstanceCollection)this[""]; }
        set { this[""] = value; }
    }
}
public class MyConfigInstanceCollection : ConfigurationElementCollection {
    protected override ConfigurationElement CreateNewElement() {
        return new MyConfigInstanceElement();
    }

    protected override object GetElementKey(ConfigurationElement element) {
        //set to whatever Element Property you want to use for a key
        return ((MyConfigInstanceElement)element).Name;
    }
}

public class MyConfigInstanceElement : ConfigurationElement {
    //Make sure to set IsKey=true for property exposed as the GetElementKey above
    [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
    public string Name {
        get { return (string) base["name"]; }
        set { base["name"] = value; }
    }

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

Here is an example of how to access the configuration information from code.

var config = ConfigurationManager.GetSection("registerCompanies") 
                 as MyConfigSection;

Console.WriteLine(config["Tata Motors"].Code);
foreach (var e in config.Instances) { 
   Console.WriteLine("Name: {0}, Code: {1}", e.Name, e.Code); 
}
like image 176
Jay Walker Avatar answered Oct 20 '22 16:10

Jay Walker


No custom configuration section necessary.

app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="YourAppSettings" type="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  </configSections>
  <!-- value attribute is optional. omit if you just want a list of 'keys' -->
  <YourAppSettings>
    <add key="one" value="1" />
    <add key="two" value="2"/>
    <add key="three" value="3"/>
    <add key="duplicate" value="aa"/>
    <add key="duplicate" value="bb"/>
  </YourAppSettings>
</configuration>

Retrieve values

// AppSettingsSection can be cast to a NameValueCollection
NameValueCollection settingCollection = 
(NameValueCollection)ConfigurationManager.GetSection("YourAppSettings");

// An array of the keys. No Duplicates
// { "one", "two", "three", "duplicate" }
string[] allKeys = settingCollection.AllKeys; 
    
// key/value pairs
// one : 1
// two : 2
// three : 3
// duplicate : bb 
foreach (string key in allKeys)
{
   Console.WriteLine(key + " : " + settingCollection[key]);
}

// Duplicates behavior
var items = settingCollection.Count;
Debug.Assert(items == 4); // no duplicates. Last element wins.
Debug.Assert(settingCollection["duplicate"] == "bb");
like image 35
JJS Avatar answered Oct 20 '22 14:10

JJS


Based on Jay Walker's answer above, this is a complete working example that adds the ability to do the indexing:

<configuration>
    <configSections>
        <section name="registerCompanies" 
                 type="My.MyConfigSection, My.Assembly" />
    </configSections>
    <registerCompanies>
        <add name="Tata Motors" code="Tata"/>
        <add name="Honda Motors" code="Honda"/>
    </registerCompanies>
</configuration>

Here is the sample code to implement a custom config section with collapsed collection

using System.Configuration;
using System.Linq;
namespace My
{
   public class MyConfigSection : ConfigurationSection
   {
      [ConfigurationProperty("", IsRequired = true, IsDefaultCollection = true)]
      public MyConfigInstanceCollection Instances
      {
         get { return (MyConfigInstanceCollection)this[""]; }
         set { this[""] = value; }
      }
   }
   public class MyConfigInstanceCollection : ConfigurationElementCollection
   {
      protected override ConfigurationElement CreateNewElement()
      {
         return new MyConfigInstanceElement();
      }

      protected override object GetElementKey(ConfigurationElement element)
      {
         //set to whatever Element Property you want to use for a key
         return ((MyConfigInstanceElement)element).Name;
      }

      public new MyConfigInstanceElement this[string elementName]
      {
         get
         {
            return this.OfType<MyConfigInstanceElement>().FirstOrDefault(item => item.Name == elementName);
         }
      }
   }

   public class MyConfigInstanceElement : ConfigurationElement
   {
      //Make sure to set IsKey=true for property exposed as the GetElementKey above
      [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
      public string Name
      {
         get { return (string)base["name"]; }
         set { base["name"] = value; }
      }

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

Here is an example of how to access the configuration information from code.

MyConfigSection config = 
   ConfigurationManager.GetSection("registerCompanies") as MyConfigSection;

Console.WriteLine(config.Instances["Honda Motors"].Code);
foreach (MyConfigInstanceElement e in config.Instances)
{
   Console.WriteLine("Name: {0}, Code: {1}", e.Name, e.Code);
}
like image 22
SwDevMan81 Avatar answered Oct 20 '22 15:10

SwDevMan81


Based on the answer by Jay Walker, accessing the elements needs to be done by iterating through the "Instances" collection. ie.

var config = ConfigurationManager.GetSection("registerCompanies") 
                 as MyConfigSection;

foreach (MyConfigInstanceElement e in config.Instances) { 
   Console.WriteLine("Name: {0}, Code: {1}", e.Name, e.Code); 
}
like image 8
Bonneech Avatar answered Oct 20 '22 15:10

Bonneech