Simplest way to store lists and dictionaries in config files
Fast and simple way of storing and using lists and dictionaries in config files
Configuration files are a useful place too keep any related configuration settings. It provides easy to use configuration fetching which you can invoke from any part of the application.
However it does not support many stuff out of the box, but on the other hand it is pretty flexible and expendable. One of the things that are not there built in is support for lists.
Most of the custom application settings are usually stored in in AppSettings configuration section. This section provides built in key/value pair data support, so in order to get list or dictionary of values there is some additional work to be done.
There are few ways to achieve lists/dictionary support for values in the config files
Custom Configuration Sections
This approach does not rely on the AppSettings section in config file. It rather relies on the custom sections that are defined in the application code and represented in the config file.
If you check the sample code in the urls mentioned below, you can clearly see that it requires 150+ lines to implement lists. This is a huge drawback if you need to configure lists/dictionaries in the configuration for a small projects. Good side of this implementation is that it is highly flexible in terms of validation, which will throw configuration exception in case config values are not correct.
This is ideal for long running large projects. For example log4net uses custom sections for its settings.
Comma-Separated values of the AppSettings element values
This is a simple workaround. The values are stored in the same AppSettings key value separated by comma character. It might work just fine for small number of simple values, but as the list grows it is getting harder to manage values.
For disctinary value it is even more complicated as there are two separators, one for key-value pairs and one for key and value split. You can see that it gets even too complicated with just four values.
<appSettings> <add key="listValue" value="LsitItem1,LsitItem2,LsitItem3,LsitItem4"/> <add key="dictionaryValue" value="DictionaryItemkKey1:DictionaryItemkValue1,DictionaryItemkKey2:DictionaryItemkValue2,DictionaryItemkKey3:DictionaryItemkValue3,DictionaryItemkKey4:DictionaryItemkValue4"/> </appSettings>
Although with C# code it is simple LINQ expression, it is still hard to maintain vallues stored under single key value.
var list = ConfigurationManager.AppSettings["listValue"].Split(','); var dictionary = ConfigurationManager.AppSettings["dictionaryValue"].Split(',').ToDictionary(k => k.Split(':').First(), v => v.Split(':').Last());
Convention over configuration approach
This is one of the approaches I often use for small projects. Basically I use convention for the lists or dictionaries key prefix. Based on the key prefix I know what type to expect and since there are multiple occurrences of the prefix in the key, I can easily build a collection object.
<appSettings> <add key="data.list.ListItemKey1" value="LsitItem1"/> <add key="data.list.ListItemKey2" value="LsitItem2"/> <add key="data.list.ListItemKey3" value="LsitItem3"/> <add key="data.list.ListItemKey4" value="LsitItem4"/> <add key="data.dictionary.DictionaryItemkKey1" value="DictionaryItemValue1"/> <add key="data.dictionary.DictionaryItemkKey2" value="DictionaryItemValue2"/> <add key="data.dictionary.DictionaryItemkKey3" value="DictionaryItemValue3"/> <add key="data.dictionary.DictionaryItemkKey4" value="DictionaryItemValue4"/> </appSettings>
You can see that is a lot cleaner and easier to identify single item and update it than in the previous approach.
Now just to read the values with simple LINQ expressions
var list = ConfigurationManager.AppSettings.AllKeys.Where(k => k.StartsWith("data.list.")).Select(k => ConfigurationManager.AppSettings[k]).ToList(); var dictionary = ConfigurationManager.AppSettings.AllKeys.Where(k => k.StartsWith("data.dictionary.")).ToDictionary(k=>k,v => ConfigurationManager.AppSettings[v]);
Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.