Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to store a collection of custom objects to an user.config file?

I would like to store a collection of custom objects in a user.config file and would like to add and remove items from the collection programmatically and then save the modified list back to the configuration file.

My items are of the following simple form:

class UserInfo {     public string FirstName { get; set; }     public string LastName { get; set; }     public string Email { get; set; }         } 

In my app.config I already created a custom section:

<configuration>   <configSections>     <section name="userInfo" type="UserInfoConfigurationHandler, MyProgram"/>    </configSections>   <userInfo>     <User firstName="John" lastName="Doe" email="[email protected]" />     <User firstName="Jane" lastName="Doe" email="[email protected]" />   </userInfo>  </configuration> 

I am also able to read in the settings by implementing IConfigurationSectionHandler:

class UserInfoConfigurationHandler : IConfigurationSectionHandler {     public UserInfoConfigurationHandler() { }      public object Create(object parent, object configContext, System.Xml.XmlNode section)     {         List<UserInfo> items = new List<UserInfo>();         System.Xml.XmlNodeList processesNodes = section.SelectNodes("User");          foreach (XmlNode processNode in processesNodes)         {             UserInfo item = new UserInfo();             item.FirstName = processNode.Attributes["firstName"].InnerText;             item.LastName = processNode.Attributes["lastName"].InnerText;             item.Email = processNode.Attributes["email"].InnerText;             items.Add(item);         }         return items;     } } 

I did all this following this article. However, using this approach I'm only able to read the settings from app.config into a List<UserInfo> collection, but I would also need to write a modified list back.

I was searching the documentation without success and now I'm kind of stuck. What am I missing?

like image 293
Dirk Vollmar Avatar asked Apr 09 '09 14:04

Dirk Vollmar


People also ask

What is app config file in C#?

App. Config is an XML file that is used as a configuration file for your application. In other words, you store inside it any setting that you may want to change without having to change code (and recompiling). It is often used to store connection strings.

Can we store an object in web config file?

Yes… We can store some object. Let’s see how I have created a sample example. In this example, I have saved an object of my custom class NewError in web.config file. And also updating it whenever required. To do this, Follow the below steps.

How do I create a custom section in a config file?

Go to your config file and add a collection. Let’s say it’s a collection of Nodes. We will create a custom section in the config file called CustomConfigSection. We need first to register it in the configSections.

How do you store a collection of objects in Java?

There's a ton of ways you can do it. Probably the easiest way to handle storing a collection of objects is by using one of the Collections provided by Java. For beginners, probably the easiest one to understand is an ArrayList, which is basically an array that grows in size dynamically depending on the amount of objects in the collection.

What is a config file?

What is a config file? It happens sometimes (quite often actually) that we need to store some parameters, default settings, framework or external libraries values and the config has been made for that purpose. How to use the AppSettings?


2 Answers

The way to add custom config (if you require more than just simple types) is to use a ConfigurationSection, within that for the schema you defined you need a ConfigurationElementCollection (set as default collection with no name), which contains a ConfigurationElement, as follows:

public class UserElement : ConfigurationElement {     [ConfigurationProperty( "firstName", IsRequired = true )]     public string FirstName     {         get { return (string) base[ "firstName" ]; }         set { base[ "firstName" ] = value;}     }      [ConfigurationProperty( "lastName", IsRequired = true )]     public string LastName     {         get { return (string) base[ "lastName" ]; }         set { base[ "lastName" ] = value; }     }      [ConfigurationProperty( "email", IsRequired = true )]     public string Email     {         get { return (string) base[ "email" ]; }         set { base[ "email" ] = value; }     }      internal string Key     {         get { return string.Format( "{0}|{1}|{2}", FirstName, LastName, Email ); }     } }  [ConfigurationCollection( typeof(UserElement), AddItemName = "user", CollectionType = ConfigurationElementCollectionType.BasicMap )] public class UserElementCollection : ConfigurationElementCollection {     protected override ConfigurationElement CreateNewElement()     {         return new UserElement();     }      protected override object GetElementKey( ConfigurationElement element )     {         return ( (UserElement) element ).Key;     }      public void Add( UserElement element )     {         BaseAdd( element );     }      public void Clear()     {         BaseClear();     }      public int IndexOf( UserElement element )     {         return BaseIndexOf( element );     }      public void Remove( UserElement element )     {         if( BaseIndexOf( element ) >= 0 )         {             BaseRemove( element.Key );         }     }      public void RemoveAt( int index )     {         BaseRemoveAt( index );     }      public UserElement this[ int index ]     {         get { return (UserElement) BaseGet( index ); }         set         {             if( BaseGet( index ) != null )             {                 BaseRemoveAt( index );             }             BaseAdd( index, value );         }     } }  public class UserInfoSection : ConfigurationSection {     private static readonly ConfigurationProperty _propUserInfo = new ConfigurationProperty(             null,             typeof(UserElementCollection),             null,             ConfigurationPropertyOptions.IsDefaultCollection     );      private static ConfigurationPropertyCollection _properties = new ConfigurationPropertyCollection();      static UserInfoSection()     {         _properties.Add( _propUserInfo );     }      [ConfigurationProperty( "", Options = ConfigurationPropertyOptions.IsDefaultCollection )]     public UserElementCollection Users     {         get { return (UserElementCollection) base[ _propUserInfo ]; }     } } 

I've kept the UserElement class simple, although it really should follow the pattern of declaring each property fully as described in this excellent CodeProject article. As you can see it represents the "user" elements in your config you provided.

The UserElementCollection class simply supports having more than one "user" element, including the ability to add/remove/clear items from the collection if you want to modify it at run-time.

Lastly there is the UserInfoSection which simply stats that it has a default collection of "user" elements.

Next up is a sample of the App.config file:

<?xml version="1.0" encoding="utf-8" ?> <configuration>   <configSections>     <sectionGroup>       <section         name="userInfo"         type="ConsoleApplication1.UserInfoSection, ConsoleApplication1"         allowDefinition="Everywhere"         allowExeDefinition="MachineToLocalUser"       />     </sectionGroup>   </configSections>    <userInfo>     <user firstName="John" lastName="Doe" email="[email protected]" />     <user firstName="Jane" lastName="Doe" email="[email protected]" />   </userInfo> </configuration> 

As you can see, in this example I've included some userInfo/user elements in the App.config. I've also added settings to say they can be defined at machine/app/user/roaming-user levels.

Next we need to know how to update them at run-time, the following code shows an example:

Configuration userConfig = ConfigurationManager.OpenExeConfiguration( ConfigurationUserLevel.PerUserRoamingAndLocal );  var userInfoSection = userConfig.GetSection( "userInfo" ) as UserInfoSection;  var userElement = new UserElement();  userElement.FirstName = "Sample"; userElement.LastName = "User"; userElement.Email = "[email protected]";  userInfoSection.Users.Add( userElement );  userConfig.Save(); 

The above code will create a new user.config file if needed, buried deep inside the "Local Settings\Application Data" folder for the user.

If instead you want the new user added to the app.config file simply change the parameter for the OpenExeConfiguration() method to ConfigurationUserLevel.None.

As you can see, it's reasonably simple, although finding this information required a bit of digging.

like image 70
Timothy Walters Avatar answered Sep 23 '22 17:09

Timothy Walters


I wouldn't store that kind of data in an app.config, at least not if it's meant to be updated programatically. Conceptually, it's for configuration settings, not application data so perhaps you want to store your username and password info in a separate XML file (assuming you can't or don't want to use a database)?

Having said that, then I think your best bet is to read in the app.config as a standard XML file, parse it, add the nodes you want and write it back. The built in ConfigurationManager API doesn't offer a way to write back new settings (which I suppose gives a hint as to Microsoft's intended use).

like image 33
Dana Avatar answered Sep 22 '22 17:09

Dana