Thursday, September 8, 2011

How to Create One or More Nested ConfigurationElementCollection items within your Custom ConfigurationSection

So recently I was trying to create nested ConfigurationElementCollection items within my custom ConfigurationSection like this:
 <Custom>  
   <Apps>  
    <App path="...">  
     <Methods>  
      <Method name="..." />  
      <Method name="..." />  
      <Method name="..." />  
     </Methods>  
    </App>  
    <App path="...">  
     <Methods>  
      <Method name="..." />  
      <Method name="..." />  
      <Method name="..." />  
     </Methods>  
    </App>  
    <App path="...">  
     <Methods>  
      <Method name="..." />  
      <Method name="..." />  
      <Method name="..." />  
     </Methods>  
    </App>  
   </Apps>  
  </Custom>  
Needless to say, I was pulling my hair out.  Finally, I found what I was looking for, so I figured I'd post my findings in such a way that you can copy/paste it straight into your code and away you go.

I modified my app.config file as follows (I've changed the names to protect the innocent):
  <configSections>  
   <section name="Custom" type="MyCustom.Custom, MyCustom" />  
  </configSections>  



and then added the above XML as well.

Then, I used the following code to implement the custom configuration:
   public class Custom : ConfigurationSection  
   {  
     [ConfigurationProperty("Apps")]  
     public AppElementCollection Apps  
     {  
       get { return this["Apps"] as AppElementCollection; }  
     }  
   }  
   public class AppElementCollection : ConfigurationElementCollection  
   {  
     protected override ConfigurationElement CreateNewElement()  
     {  
       return new AppElement();  
     }  
     protected override object GetElementKey(ConfigurationElement element)  
     {  
       return ((AppElement)element).LocalName;  
     }  
     public override ConfigurationElementCollectionType CollectionType  
     {  
       get { return ConfigurationElementCollectionType.BasicMap; }  
     }  
     protected override string ElementName  
     {  
       get { return "App"; }  
     }  
     public AppElement this[int index]  
     {  
       get { return (AppElement)BaseGet(index); }  
       set  
       {  
         if (BaseGet(index) != null)  
         {  
           BaseRemoveAt(index);  
         }  
         BaseAdd(index, value);  
       }  
     }  
     new public AppElement this[string employeeID]  
     {  
       get { return (AppElement)BaseGet(employeeID); }  
     }  
     public bool ContainsKey(string key)  
     {  
       bool result = false;  
       object[] keys = BaseGetAllKeys();  
       foreach (object obj in keys)  
       {  
         if ((string)obj == key)  
         {  
           result = true;  
           break;  
         }  
       }  
       return result;  
     }  
   }  
   public class AppElement : ConfigurationElement  
   {  
     [ConfigurationProperty("path", IsRequired = true, IsKey = true)]  
     public string LocalName  
     {  
       get  
       {  
         return this["path"] as string;  
       }  
       set  
       {  
         this["path"] = value;  
       }  
     }  
     [ConfigurationProperty("Methods")]  
     public MethodElementCollection Methods  
     {  
       get  
       {  
         return this["Methods"] as MethodElementCollection;  
       }  
     }  
   }  
   public class MethodElementCollection : ConfigurationElementCollection  
   {  
     protected override ConfigurationElement CreateNewElement()  
     {  
       return new MethodElement();  
     }  
     protected override object GetElementKey(ConfigurationElement element)  
     {  
       return ((MethodElement)element).LocalName;  
     }  
     public override ConfigurationElementCollectionType CollectionType  
     {  
       get { return ConfigurationElementCollectionType.BasicMap; }  
     }  
     protected override string ElementName  
     {  
       get { return "Method"; }  
     }  
     public MethodElement this[int index]  
     {  
       get { return (MethodElement)BaseGet(index); }  
       set  
       {  
         if (BaseGet(index) != null)  
         {  
           BaseRemoveAt(index);  
         }  
         BaseAdd(index, value);  
       }  
     }  
     new public MethodElement this[string employeeID]  
     {  
       get { return (MethodElement)BaseGet(employeeID); }  
     }  
     public bool ContainsKey(string key)  
     {  
       bool result = false;  
       object[] keys = BaseGetAllKeys();  
       foreach (object obj in keys)  
       {  
         if ((string)obj == key)  
         {  
           result = true;  
           break;  
         }  
       }  
       return result;  
     }  
   }  
   public class MethodElement : ConfigurationElement  
   {  
     [ConfigurationProperty("name", IsRequired = true, IsKey = true)]  
     public string LocalName  
     {  
       get  
       {  
         return this["name"] as string;  
       }  
       set  
       {  
         this["name"] = value;  
       }  
     }  
   }  
I think that should be enough information to get you going.  :)

4 comments:

Krishna Sapkota said...

Thank you very much, it saved my whole night, its awesome post!

Krishna Sapkota said...
This comment has been removed by a blog administrator.
Prashant said...

you are life saver. Thank you very much

nsetrader.com said...

Thank you TED you saved a lot of frustration and blood