1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Collections.Specialized; 6 using System.Globalization; 7 8 namespace System.Configuration 9 { 10 /// <summary> 11 /// The AppSettingsReader class provides a wrapper for System.Configuration.ConfigurationManager.AppSettings 12 /// which provides a single method for reading values from the config file of a particular type. 13 /// </summary> 14 public class AppSettingsReader 15 { 16 private NameValueCollection _map; 17 private static Type s_stringType = typeof(string); 18 private static Type[] _paramsArray = new Type[] { s_stringType }; 19 private static string NullString = "None"; 20 AppSettingsReader()21 public AppSettingsReader() 22 { 23 _map = System.Configuration.ConfigurationManager.AppSettings; 24 } 25 26 /// <summary> 27 /// Gets the value for specified key from ConfigurationManager.AppSettings, and returns 28 /// an object of the specified type containing the value from the config file. If the key 29 /// isn't in the config file, or if it is not a valid value for the given type, it will 30 /// throw an exception with a descriptive message so the user can make the appropriate 31 /// change 32 /// </summary> GetValue(string key, Type type)33 public object GetValue(string key, Type type) 34 { 35 if (key == null) throw new ArgumentNullException(nameof(key)); 36 if (type == null) throw new ArgumentNullException(nameof(type)); 37 38 string val = _map[key]; 39 40 if (val == null) throw new InvalidOperationException(string.Format(SR.AppSettingsReaderNoKey, key)); 41 42 if (type == s_stringType) 43 { 44 // It's a string, so we can ALMOST just return the value. The only 45 // tricky point is that if it's the string "(None)", then we want to 46 // return null. And of course we need a way to represent the string 47 // (None), so we use ((None)), and so on... so it's a little complicated. 48 int NoneNesting = GetNoneNesting(val); 49 if (NoneNesting == 0) 50 { 51 // val is not of the form ((..((None))..)) 52 return val; 53 } 54 else if (NoneNesting == 1) 55 { 56 // val is (None) 57 return null; 58 } 59 else 60 { 61 // val is of the form ((..((None))..)) 62 return val.Substring(1, val.Length - 2); 63 } 64 } 65 else 66 { 67 try 68 { 69 return Convert.ChangeType(val, type, CultureInfo.InvariantCulture); 70 } 71 catch (Exception) 72 { 73 string displayString = (val.Length == 0) ? SR.AppSettingsReaderEmptyString : val; 74 throw new InvalidOperationException(string.Format(SR.AppSettingsReaderCantParse, displayString, key, type.ToString())); 75 } 76 } 77 } 78 GetNoneNesting(string val)79 private int GetNoneNesting(string val) 80 { 81 int count = 0; 82 int len = val.Length; 83 if (len > 1) 84 { 85 while (val[count] == '(' && val[len - count - 1] == ')') 86 { 87 count++; 88 } 89 if (count > 0 && string.Compare(NullString, 0, val, count, len - 2 * count, StringComparison.Ordinal) != 0) 90 { 91 // the stuff between the parens is not "None" 92 count = 0; 93 } 94 } 95 return count; 96 } 97 } 98 } 99