Feed Subscribe
Exception has been thrown by the target of an invocation.


AppSettingsReader and reading typed and nullable application settings

by ondrejsv 8. January 2008 21:38

I'm pretty sure that almost every .NET developer has heard of the possibility to include various application settings in the configuration file (app.config or web.config). Application settings are just plain string key-value pairs we used to store in the past inside plethora of .ini files and in the Registry. A common way to read them in the .NET framework is to use the static AppSettings property of the ConfigurationManager class. This property returns an object of the NameValueCollection type containing the application settings key-value pairs.

However, there is a class named AppSettingsReader which is a wrapper around the AppSettings collection and I found that only a few know it. The only "useful" method (i.e. not inherited from the Object class) is the GetValue method. It takes two parameters: key of the application settings item we want to retrieve and type to convert the value to, so we don't need to convert the value manually. Another difference over directly using AppSettings is that this method throws InvalidOperationException if no item with the specified key is present.

Suppose we have a configuration file as following:

<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="Color" value="Red"/> <add key="FailAttemptCount" value="5" /> </appSettings> </configuration>

We may then use the following snippet to read these settings:

AppSettingsReader appSettingsReader = new AppSettingsReader(); Console.WriteLine( appSettingsReader.GetValue("Color", typeof(string))); int failCount = (int) appSettingsReader.GetValue("FailAttemptCount", typeof(int));

Internally GetValue uses the ChangeType method of the Convert class to explicitly convert the read value. However, GetValue returns the value as object so we must use a formal downcast to assign the value to a typed variable (see below for a possible solution). Note that the Convert class supports converting only to .NET base types.

There is another feature of the AppSettingsReader which is undocumented as far as I know. For string values you may use "(None)" as value to indicate there is in fact no value but the setting is present. In a rare case you want to have "(None)" as a valid value, just enclose it within parenthesis. If we introduce these values to our configuration file:

<add key="PreferredName" value="(None)"/> <add key="NoneString" value="((None))"/>

then

appSettingsReader.GetValue("PreferredName", typeof(string))

returns a null string and

appSettingsReader.GetValue("NoneString", typeof(string))

returns "(None)" as value.

As I've mentioned, in the original implementation this trick works only for string values but it is straightforward to extend it to other types. In the attached demonstration project you can find MyAppSettingsReader class -- an implementation derived from AppSettingsReader. Then if we have:

<add key="PreferredName" value="(None)"/>

then

int? maxOpenFiles = (int?)myAppSettingsReader.GetValue("MaxOpenFiles", typeof(int?));

maxOpenFiles will be assigned a null value.

Last note: the final downcast is very annoying and indeed it could be made unnecessary by implementing GetValue method as a generic one. With introduction of extension methods, we can atone this very easily with no access to original code and even without creating a derived class:

public static T GetValue<T>(this AppSettingsReader appSetReader,string key) { return (T)appSetReader.GetValue(key, typeof(T)); }

Then we may use it just like:

Console.WriteLine( appSettingsReader.GetValue<string>("Color")); failCount = appSettingsReader.GetValue<int>("FailAttemptCount");

I attached a demonstration project so be sure to have a look at it.

kick it on DotNetKicks.com

Tags:

Pingbacks and trackbacks (3)+

Comments are closed