C# 自定义配置文件

时间:2022-08-30 20:56:48

配置文件有两种设置方式,第一种是直接在网站根目录下的web.config中设置;第二种方式是自定义配置文件,在web.config中指定其他配置文件的路径。

第一种:除了在常用的appSettings节点下进行<add/>添加,还可以在<configSections>节点下设置<section/>节点,具体如下:

  <configSections>
    <!--以NameValue键值/对的形式返回配置节中的信息-->
    <section name="Person" type="System.Configuration.NameValueSectionHandler"/>
    <!--以Dictionary字典键值对的形式返回配置节中的信息-->
    <section name="Man" type="System.Configuration.DictionarySectionHandler"/>
    <!--基础结构。处理 .config 文件中由单个 XML 标记所表示的各配置节。-->
    <section name="Name" type="System.Configuration.SingleTagSectionHandler" />
  </configSections>
  <!--自定义配置节点-->
  <Person>
    <add key="老大" value="刘备" />
    <add key="老二" value="关羽" />
    <add key="老三" value="张飞" />
  </Person>
  <Man>
    <add key="老大" value="曹操" />
    <add key="老二" value="典韦" />
    <add key="老三" value="郭嘉" />
  </Man>
  <!--注意是要单个节SingleTagSectionHandler才能处理,但是无论你索性有多少个也能处理-->
  <Name one="1" two="2" three="3" four="4" five="5" />

调用方式:

        /// <summary>
        /// 获取配置文件
        /// </summary>
        private static void GetConfigs()
        {
            //读取人名
            NameValueCollection nvc = (NameValueCollection)ConfigurationManager.GetSection("Person");
            foreach (string key in nvc.AllKeys)
            {
                Console.WriteLine(key + ":" + nvc[key]);
            }

            //读取男人
            IDictionary dict = (IDictionary)ConfigurationManager.GetSection("Man");
            foreach (string key in dict.Keys)
            {
                Console.WriteLine(key + ":" + dict[key]);
            }

            IDictionary dict1 = (IDictionary)ConfigurationManager.GetSection("Name");
            foreach (string key in dict1.Keys)
            {
                Console.WriteLine(key + ":" + dict1[key]);
            }
        }

其中Section节点里面的name是自定义节点的名称,type是接收配置节中的信息的数据类型。第一种方式可以使用.Net自带的几种数据类型进行装载数据,如:NameValue键值对、Dictionary字典和SingleTag基础结构。

 

第二种:在自定义配置文件中设置自定义的数据结构,通过指定文件路径加载配置文件,具体如下:

  <configSections>
    <!--把Framework节点的数据映射到ConfigFile类中-->
    <section name="Framework" type="ConsoleApplication.ConfigFiles.ConfigFile,ConsoleApplication"/>
  </configSections>
  <!--自定义配置节点-->
  <Framework configSource="ConfigFiles\Framework.config"/>

自定义配置文件结构:

<Framework>
  <Configs>
    <add key="WebHost" value="127.0.0.1" description="网站基础地址"/>
    <add key="LogTimer" value="10" description="日志定时写入的时间间隔,单位秒。"/>
  </Configs>
</Framework>

第二种方式中,Framework节点不再是key-value形式的,而是完全自定义的结构,并且在Framework节点下还有子节点<Configs>,此时不能通过.Net自带的三种数据类型进行装载,只能自定义一种接收Framework的数据类,如:

  /// <summary>
    /// 配置文件类
    /// </summary>
    public class ConfigFile : ConfigurationSection
    {
        /// <summary>
        /// 配置节点
        /// </summary>
        /// <value>配置集合</value>
        [ConfigurationProperty("Configs", IsDefaultCollection = true)]
        public ConfigNodeCollection Configs
        {
            get
            {
                return (ConfigNodeCollection)base["Configs"];
            }
        }

        /// <summary>
        /// 获取配置字段值
        /// </summary>
        /// <param name="key">配置Key</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>配置值</returns>
        public string GetValueWithKey(string key, string defaultValue = "")
        {
            return this.Configs.GetValueWithKey(key, defaultValue);
        }
    }

    /// <summary>
    /// 配置节点列表
    /// </summary>
    public class ConfigNodeCollection : ConfigurationElementCollection
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public ConfigNodeCollection()
        {
            ConfigNode element = this.CreateNewElement() as ConfigNode;
        }

        /// <summary>
        /// 根据索引获取配置节点
        /// </summary>
        /// <param name="index">索引值</param>
        /// <returns>配置节点</returns>
        public ConfigNode this[int index]
        {
            get
            {
                return this.BaseGet(index) as ConfigNode;
            }

            set
            {
                if (this.BaseGet(index) != null)
                {
                    this.BaseRemoveAt(index);
                }

                this.BaseAdd(index, value);
            }
        }

        /// <summary>
        /// 获取配置字段值
        /// </summary>
        /// <param name="key">配置Key</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns>配置值</returns>
        public string GetValueWithKey(string key, string defaultValue = "")
        {
            // 如果Key不存在则抛出异常
            if (string.IsNullOrWhiteSpace(key))
            {
                throw new Exception("get Config Key is null");
            }

            // 查找Key的值 // Key值忽略大小写
            foreach (ConfigNode item in this)
            {
                if (item.Key.ToLower().Equals(key.ToLower()))
                {
                    return item.Value;
                }
            }

            // 如果默认值不为空,返回默认值
            if (!string.IsNullOrWhiteSpace(defaultValue))
            {
                return defaultValue;
            }

            // 抛出未找到Key的异常
            throw new Exception(string.Format("Key:{0} Is not find!", key));
        }

        /// <summary>
        /// 创建节点函数
        /// </summary>
        /// <returns>节点对象</returns>
        protected override ConfigurationElement CreateNewElement()
        {
            return new ConfigNode();
        }

        /// <summary>
        /// 获取节点Key
        /// </summary>
        /// <param name="element">节点对象</param>
        /// <returns>节点Key值</returns>
        protected override object GetElementKey(ConfigurationElement element)
        {
            ConfigNode serverElement = element as ConfigNode;
            return serverElement.Key;
        }
    }

    /// <summary>
    /// 配置节点
    /// </summary>
    public class ConfigNode : ConfigurationElement
    {
        [ConfigurationProperty("key", IsRequired = true)]
        public string Key
        {
            get
            {
                return base["key"].ToString();
            }
            set
            {
                base["key"] = value;
            }
        }

        [ConfigurationProperty("value", IsRequired = true)]
        public string Value
        {
            get
            {
                return base["value"].ToString();
            }
            set
            {
                base["value"] = value;
            }
        }

        [ConfigurationProperty("description", IsRequired = true)]
        public string Description
        {
            get
            {
                return base["description"].ToString();
            }
            set
            {
                base["description"] = value;
            }
        }
    }

调用如下:

        /// <summary>
        /// 获取自定义配置文件
        /// </summary>
        private static void GetConfigs() {
            ConfigFile config = ConfigurationManager.GetSection("Framework") as ConfigFile;
            if (config == null)
            {
                throw new Exception("未找到对应节点");
            }
            string WebHost = config.GetValueWithKey("WebHost");
            string LogTimer = config.GetValueWithKey("LogTimer");
            Console.WriteLine("WebHost:"+WebHost);
            Console.WriteLine("LogTimer:"+LogTimer);
        }

其中用到了.Net自带的几个数据类:ConfigurationSection、ConfigurationElementCollection、ConfigurationElement和ConfigurationProperty,它们都是跟配置节点相关的类,有兴趣的可以深入了解下。

至此,自定义配置文件就搞定了,在大型项目中或者在与多个外部系统有接口交互的项目中会需要用到多配置文件,都在web.config里写不利于维护。采用第二种方式,只需在web.config文件中配置路径,如需修改配置只需要修改自定义配置文件即可,这样也可以避免修改web.config导致Session丢失。