When using C#, I am kinda a strongly typed bigot and like to use the compiler as much as I can. Since practically every application I have ever worked on has had some sort of setting access from a config file, I felt that there had to be a better way.
So, given this config file:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="StringSetting" value="filepath"/> <add key="BoolSetting" value="true"/> <add key="StringListDelimitedSetting" value="one;two;three"/> </appSettings> </configuration>
I don’t want to litter my code with this everywhere:
//BAD string value = System.Configuration.ConfigurationManager.AppSettings["StringSetting"]; if (value == "SOMETHING") { //do something } //WORSE? string boolValue = System.Configuration.ConfigurationManager.AppSettings["BoolSetting"]; if (boolValue == "YES") { //do something } //PRODUCES STRONG TYPE BUT EVEN MORE CODE string someOtherBoolValue = System.Configuration.ConfigurationManager.AppSettings["SomeOtherBoolSetting"]; bool strongBoolValue; if (Boolean.TryParse(someOtherBoolValue, out strongBoolValue)) { if (strongBoolValue) { //do something } }
So, this is what I do to keep my “stringly” typed settings in one place, strongly typed and make them easily accessible in my code:
public static class AppSettingsExtensions { public static string StringSetting(this NameValueCollection settings) { string setting = settings["StringSetting"]; if (setting != null && !string.IsNullOrWhiteSpace(setting)) { return setting; } return string.Empty; } public static bool BoolSetting(this NameValueCollection settings) { string setting = settings["BoolSetting"]; if (setting != null && !string.IsNullOrWhiteSpace(setting)) { bool test; if (Boolean.TryParse(setting, out test)) { return test; } } return false; } public static IEnumerable<string> StringListDelimitedSetting(this NameValueCollection settings) { string setting = settings["StringListDelimitedSetting"]; if (setting != null && !string.IsNullOrWhiteSpace(setting)) { return setting.Split(Convert.ToChar(";"), Convert.ToChar(",")).ToList(); } return Enumerable.Empty<string>(); } }
Accessing settings in code now is simple and gives you a strong type:
//GOOD string stringSetting = ConfigurationManager.AppSettings.StringSetting(); if (stringSetting == "SOMETHING") { //do something } //OR bool boolSetting = ConfigurationManager.AppSettings.BoolSetting(); if (boolSetting) { //do something } //OR IEnumerable<string> listSettings = ConfigurationManager.AppSettings.StringListDelimitedSetting(); foreach (string setting in listSettings) { //do something }
And yes, this works for connections strings as well, just change the type of the extension:
public static class ConnectionStringExtensions { public static string SomeConnectionString(this ConnectionStringSettingsCollection settings) { ConnectionStringSettings setting = settings["SomeConnectionString"]; if (setting != null) { string connectionString = setting.ConnectionString; if (!string.IsNullOrWhiteSpace(connectionString)) { return connectionString; } } return string.Empty; } }
Accessed like:
string connectionString = ConfigurationManager.ConnectionStrings.SomeConnectionString();
And there you have it, that is a tool I like to keep in my toolbox when working with configuration files.
Be First to Comment