/// <summary> /// Provides access to configuration sections and gets the section name and /// type information. /// /// Reads the name (which is the name of the element that contains the information the section handler reads) /// and type (which is the name of the type that reads the information) attributes of each configuration section. /// /// Activates the types specified in the type attribute (said as congiguration object) /// and stores the configuration object in a Hashtable with the /// value in the name attribute as the key. /// </summary> /// /// <remarks> /// /// All the exception messages are being hard-coded in the method body itself to keep the /// code simple. /// /// Probably you could write your own message management utility and re-write the /// method, so that the messages are getting picked up from the resource file. /// /// </remarks> public static void ReadConfigurationSettings() { String sectionName = null; String typeName = null; String[] typeNames = null; Char typeSeparator = Convert.ToChar(","); XmlDocument configDocument = null; XmlNodeList configNodes = null; XmlNodeList sectionNodes = null; Assembly sectionHandlerAssembly = null; Type sectionHandlerType = null; ReadOnlyNameValueCollection appSettingsCollection = new ReadOnlyNameValueCollection(); XmlNodeList appSettingsNodes = null; if (isActivated) { return; } try { isActivated = true; //Get the physical path of the executing assembly (excluding the assembly name) Char directorySeparator = Convert.ToChar("/"); Char altDirectorySeparator = Convert.ToChar(@"\"); String configFileName = Assembly.GetExecutingAssembly().GetName().CodeBase; if (configFileName.IndexOf(directorySeparator) > -1) { configFileName = configFileName.Substring(0, configFileName.LastIndexOf(directorySeparator)) + directorySeparator.ToString() + "SmartConfig.xml";; } else if (configFileName.IndexOf(altDirectorySeparator) > -1) { configFileName = configFileName.Substring(0, configFileName.LastIndexOf(altDirectorySeparator)) + altDirectorySeparator.ToString() + "SmartConfig.xml";; } else { throw new System.IO.FileNotFoundException(); } //Declare a XML document object and Load the xml file configDocument = new XmlDocument(); configDocument.Load(configFileName); configNodes = configDocument.GetElementsByTagName("configSections"); //return if no <configSections> are declared if (configNodes.Count == 0) { return; } //Oops!! more than one <configSections> defined if (configNodes.Count > 1) { throw (new Exception("Configuration file cannot contain more than one configSections element")); } //Get all the section elements sectionNodes = configNodes.Item(0).ChildNodes; //return if the <configSections> is an empty element if (sectionNodes.Count == 0) { return; } //iterate through the Nodelist for each section node foreach (XmlElement sectionNode in sectionNodes) { //get the section name sectionName = sectionNode.GetAttribute("name"); //get the type name typeName = sectionNode.GetAttribute("type"); if (sectionName == null) { throw (new Exception("Invalid configuration section declaration. Section name cannot be null.")); } if (typeName == null) { throw (new Exception("Invalid configuration section declaration. Type name cannot be null.")); } //get the type name and its encompassing aseembly name typeNames = sectionNode.GetAttribute("type").Split(typeSeparator); if (typeNames.Length < 2) { throw (new Exception("Invalid type attribute.")); } //Load the configuration types' encompassing assembly sectionHandlerAssembly = Assembly.Load(typeNames[1]); //get the System.Type with the specified name sectionHandlerType = sectionHandlerAssembly.GetType(typeNames[0], true); //iteterate through the System.Type[] array which //stores all the implemented interfaces to check whether //the type implements IConfigSectionHandler interface foreach (Type interfaceType in sectionHandlerType.GetInterfaces()) { if (interfaceType.Name == "IConfigSectionHandler") { //instantiate the type to create the configuration object Object handlerInstance = Activator.CreateInstance(sectionHandlerType); //get the "Create" method attributes MethodInfo methodInfo = sectionHandlerType.GetMethod("Create"); //define the method parameters Object[] methodParams = new Object[1]; methodParams[0] = configDocument.GetElementsByTagName(sectionName).Item(0); //add the configuration object to the hashtable ConfigurationSettings.AddConfigurationSettings(sectionName, methodInfo.Invoke(handlerInstance, methodParams)); } } //Get the "appSettings" appSettingsNodes = configDocument.GetElementsByTagName("appSettings"); if (appSettingsNodes != null) { if (appSettingsNodes.Count > 1) { //Oops!! More than one "<appSettings>" section throw new Exception("Configuration file cannot contain more than one appSettings section."); } //Get the children - (all the <add> nodes) XmlNodeList appSettingsChildNodes = appSettingsNodes[0].ChildNodes; try { if (appSettingsChildNodes.Count > 0) { foreach (XmlNode node in appSettingsChildNodes) { //Add the key-value pairs to the collection appSettingsCollection.Add(node.Attributes["key"].Value, node.Attributes["value"].Value); } } //Put the collection in the ConfigurationSettings class ConfigurationSettings.AddAppSettings(appSettingsCollection); } catch (Exception ex) { throw new Exception("Error occured while accessing the application settings", ex); } } } } catch { throw; //Probably you could write your own custom application exception class deriving from //System.ApplicationException and wrap the exception before being rethrown. } finally { } }
/// <summary> /// Adds the application settings and marks the collection as read only /// </summary> /// <param name="collection"></param> internal static void AddAppSettings(ReadOnlyNameValueCollection collection) { appSettingsStore = collection; appSettingsStore.SetReadOnly(); }