Add custom configuration node methods in web.config and app.config files

  • 2020-06-03 08:09:11
  • OfStack

Experienced developers know that in the development. NET applications can take advantage of the configuration file save 1 some commonly used and is likely to change information, such as save the path of the log file, the database connection information and so on, so that even if the parameters in the production of information and the development environment is not 1 to also only need to change the configuration file rather than changes in the source code and recompile, extremely convenient. And we also agreed 1 general, in < appSettings > The node saves the application's configuration information in < connectionStrings > To save database connection string information.

The above methods and conventions are good enough for most development purposes, but in some cases some configuration information can be grouped into groups that are not intuitive or easy to read, as mercifully with.NET. If you have used Log4Net or ES13en.Caching, you will be familiar with the following configuration:


<sectionGroup name="enyim.com"><section name="memcached" 
type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching" /></sectionGroup>

Or:

<configSections><section name="log4net" type="System.Configuration.IgnoreSectionHandler"/></configSections>

In the configuration file that appears above, we will find nodes named "enyim.com" or "log4net". Although they are not the default nodes of the config file, the program will run without error after passing the configuration above. In this way, the relevant configuration information can also be well categorized and stored.

Here I show a simple example, the example from my 1 since 2006 began to develop self-use software (because not beautify so there is no free release), in this application connfig file I added 1 some unique configuration, so a new one node, app. config file content is as follows:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration>   
   <configSections>       
    <section name="SoftwareSettings" type="ImageAssistant.Configuration.SoftwareSettings, ImageAssistant" />   
   </configSections>   
     <SoftwareSettings>     
       <LoadSettings>       
         <add key="LoadBmp" value="true"/>       
         <add key="LoadJpg" value="true"/>       
         <add key="LoadGif" value="true"/>       
         <add key="LoadPng" value="false"/>     
       </LoadSettings>     
     <PathSettings SavePath="C:\ResizeImages\" SearchSubPath="true"/>   
   </SoftwareSettings>   
   <appSettings>     
      <add key="LoadBmp" value="true"/>     
      <add key="LoadJpg" value="true"/>     
      <add key="LoadGif" value="true"/>     
      <add key="LoadPng" value="false"/>    
      <add key="IncludeSubPath"  value="true"/>  
   </appSettings>     
</configuration>

In the config file we use < section name="SoftwareSettings" type="ImageAssistant.Configuration.SoftwareSettings, ImageAssistant" / > Tells the application that for the SoftwareSettings node in the configuration file, its corresponding class is the ES40en.Configuration.SoftwareSettings class in the ImageAssistant assembly, and in the < SoftwareSettings > We also see in the nodes that there are < LoadSettings > Nodes and < PathSettings > Node, where < LoadSettings > Is a collection of nodes containing multiple children. To show these relationships we need to add four classes: SoftwareSettings, LoadSettingsCollection, LoadSettingsElement and PathSettingElement. For ease of publication, I put the code for the four classes in a physical file as follows (note the addition of references to System.Configuration.dll) :

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Configuration;  

namespace ImageAssistant.Configuration  
{  
    public sealed class LoadSettingsCollection : ConfigurationElementCollection  
    {  
        private IDictionary<string, bool> settings;  

        protected override ConfigurationElement CreateNewElement()  
        {  
            return new LoadSettingsElement();  
        }  

        protected override object GetElementKey(ConfigurationElement element)  
        {  
            LoadSettingsElement ep = (LoadSettingsElement)element;  

            return ep.Key;  
        }  

        protected override string ElementName  
        {  
            get  
            {  
                return base.ElementName;  
            }  
        }  

        public IDictionary<string, bool> Settings  
        {  
            get  
            {  
                if (settings == null)  
                {  
                    settings = new Dictionary<string, bool>();  
                    foreach (LoadSettingsElement e in this)  
                    {  
                        settings.Add(e.Key, e.Value);  
                    }  
                }  
                return settings;  
            }  
        }  

        public bool this[string key]  
        {  
            get  
            {  
                bool isLoad = true;  
                if (settings.TryGetValue(key, out isLoad))  
                {  
                    return isLoad;  
                }  
                else  
                {  
                    throw new ArgumentException(" No on '" + key + "' The nodes are configured. ");  
                }  
            }  
        }  

    }  

    public class LoadSettingsElement : ConfigurationElement  
    {  
        [ConfigurationProperty("key", IsRequired = true)]  
        public string Key  
        {  
            get { return (string)base["key"]; }  
            set { base["key"] = value; }  
        }  
        [ConfigurationProperty("value", IsRequired = true)]  
        public bool Value  
        {  
            get { return (bool)base["value"]; }  
            set { base["value"] = value; }  
        }  
    }  

    public class PathSettingElement : ConfigurationElement  
    {  
        /// <summary>   
        ///    
        /// </summary>   
        [ConfigurationProperty("SavePath", IsRequired = true)]  
        public string SavePath  
        {  
            get { return (string)base["SavePath"]; }  
            set { base["SavePath"] = value; }  
        }  
        /// <summary>   
        ///    
        /// </summary>   
        [ConfigurationProperty("SearchSubPath", IsRequired = false, DefaultValue = true)]  
        public bool SearchSubPath  
        {  
            get { return (bool)base["SearchSubPath"]; }  
            set { base["SearchSubPath"] = value; }  
        }  
    }  

    /// <summary>   
    ///  The corresponding config In the file    
    /// </summary>   
    public sealed class SoftwareSettings : ConfigurationSection  
    {  
        /// <summary>   
        ///  The corresponding SoftwareSettings Under the node LoadSettings Child nodes    
        /// </summary>   
        [ConfigurationProperty("LoadSettings", IsRequired = true)]  
        public LoadSettingsCollection LoadSettings  
        {  
            get { return (LoadSettingsCollection)base["LoadSettings"]; }  
        }  

        /// <summary>   
        ///  The corresponding SoftwareSettings Under the node PathSettings Child nodes, not required    
        /// </summary>   
        [ConfigurationProperty("PathSettings", IsRequired = false)]  
        public PathSettingElement PathSetting  
        {  
            get { return (PathSettingElement)base["PathSettings"]; }  
            set { base["PathSettings"] = value; }  
        }  

    }  
}

In the above code, you can see the property ConfigurationProperty, which is the name of the property in the config file, IsRequired, which is the required property, and DefaultValue, which is the default value of the property. Besides the first time, we should also pay attention to the following relations:
SoftwareSettings: Root node, inherited from ConfigurationSection.
LoadSettingsCollection: Collection of child nodes, inherited from ConfigurationElementCollection.
LoadSettingsElement: Child node, inherited from ConfigurationElement.
PathSettingElement: Child node, inherited from ConfigurationElement.
After writing the following code, how do we use the above class? In fact, it's as simple as this:

class Program  
    {  
        static void Main(string[] args)  
        {  
            SoftwareSettings softSettings = ConfigurationManager.GetSection("SoftwareSettings") as SoftwareSettings;  

            foreach (string key in softSettings.LoadSettings.Settings.Keys)  
            {  
                Console.WriteLine("{0}={1}", key, softSettings.LoadSettings[key]);  
            }  
            Console.WriteLine("SavePath={0},SearchSubPath={1}", softSettings.PathSetting.SavePath, softSettings.PathSetting.SearchSubPath);  
            Console.ReadLine();  
        }  
    }

The results of this program are as follows:
LoadBmp=True
LoadJpg=True
LoadGif=True
LoadPng=False
SavePath=C:/ResizeImages/,SearchSubPath=True

Summary: approved in the config file above < appSettings > A similar effect is achieved, but with custom nodes we can easily read the relevant application configuration and maintain it easily. If you encounter a similar situation in this article during development, take the approach described in this article.


Related articles: