C# 动态修改配置文件

    近期工作太忙了,都没有时间上上博客,生活所困,得工作呀,相信很多人都是这样。

    近期由于项目对配置文件的操作多了,原来参考网络的同僚思想写了个读和写配置的类,但都是针对appSettings 节点,对配置节没有更多的实现,但很多项目如果配置的内容多了,以配置节来分类比较清晰(有很多配置直接使用XML,但我还是偏好Frameword带schema的config文件)。现在写下自己的实现,以方便大家参考(此处的配置文件是指独立的config文件,不是App.config文件)。

1、扩展Configuration类的功能。些功能使用Framework的扩展方法,使用起来更象是Configuration的功能一样。扩展方法不是本文件要介绍的内容。

命名空间:namespace System.Configuration

和Configuration的命名空间相同,虽然有时忘记引入该扩展类所在的程序集,以导致扩展方法不知道在哪里,但本人觉得使用相同的命名空间,更加似Configuration的功能。

类名:public static class ConfigurationExtensions     扩展方法得使用静态类。

2、实现:在网上,有位仁兄使用自定义一个Section节来实现NameValue的做法,虽然的可行,但在配置节的设置上得带有自己的程序集的限定名等,本人不喜欢,Framework都有NameValeElement 和 KeyValueElement等的定义,相似的做法,我们又何必多些一番工作!不过还多谢哪位高手的代码,做了不少参考。(本人发觉Microsoft随着新版本的更新,以前很多可以直接操作其本框架的功能都被屏蔽了,不知道是否制约做IDE工具的开源框架,以减少对VS的竞争的原因吧)。还有位高手直接通过XMLDocumet来操作,应该也不是好的解决方案。

扩展Configuration的功能 

获取连接字符串

View Code
        ///<summary>依据连接串名字connectionName返回数据连接字符串 </summary> 
        
///<param name="connectionName">连接串的</param> 
        
///<param name="config"></param>
        
///<returns></returns> 
        public static string GetConnectionStringsConfig(this Configuration config, string connectionName)
        {
            string connectionString = config.ConnectionStrings.ConnectionStrings[connectionName].ConnectionString;
            ////Console.WriteLine(connectionString); 
            return connectionString;
        }

 

更新连接字符串

View Code
        ///<summary> 
        
///更新连接字符串  
        
///</summary> 
        
///<param name="newName">连接字符串名称</param> 
        
///<param name="newConString">连接字符串内容</param> 
        
///<param name="newProviderName">数据提供程序名称</param> 
        
///<param name="config">Configuration实例</param>
        public static void UpdateConnectionStringsConfig(this Configuration config, string newName, string newConString, string newProviderName)
        {
            bool isModified = false;
            //记录该连接串是否已经存在      
            
//如果要更改的连接串已经存在      
            if (config.ConnectionStrings.ConnectionStrings[newName] != null)
            { isModified = true; }

            //新建一个连接字符串实例      
            ConnectionStringSettings mySettings = new ConnectionStringSettings(newName, newConString, newProviderName);

            // 如果连接串已存在,首先删除它      
            if (isModified)
            {
                config.ConnectionStrings.ConnectionStrings.Remove(newName);
            }
            // 将新的连接串添加到配置文件中.      
            config.ConnectionStrings.ConnectionStrings.Add(mySettings);
            // 保存对配置文件所作的更改      
            config.Save(ConfigurationSaveMode.Modified);
        }

 

获取appSettings配置节的value项

View Code
        ///<summary> 
        
///返回config文件中appSettings配置节的value项  
        
///</summary> 
        
///<param name="strKey"></param> 
        
///<param name="config">Configuration实例</param>
        
///<returns></returns> 
        public static string GetAppSettingsItemValue(this Configuration config, string strKey)
        {
            foreach (KeyValueConfigurationElement key in config.AppSettings.Settings)
            {
                if (key.Key == strKey)
                {
                    return config.AppSettings.Settings[strKey].Value;
                }
            }
            return string.Empty;
        }

 

获取所有的appSettings的节点

View Code
        /// <summary>
        
/// 获取所有的appSettings的节点。
        
/// </summary>
        
/// <param name="config"></param>
        
/// <returns></returns>
        public static Dictionary<string,string> GetAppSettings(this Configuration config)
        {
            Dictionary<string,string> dict = new Dictionary<string,string>();
            foreach (KeyValueConfigurationElement key in config.AppSettings.Settings)
            {
                dict[key.Key] = key.Value;
            }
            return dict;
        }

 

更新或增加appSettings配置节增加一对键、值对。

View Code
        ///<summary>  
        
///更新在config文件中appSettings配置节增加一对键、值对。
        
///</summary>  
        
///<param name="newKey"></param>  
        
///<param name="newValue"></param>  
        
///<param name="config"></param>
        public static void UpdateAppSettingsItemValue(this Configuration config, string newKey, string newValue)
        {
            UpdateAppSettingsItemNoSave(config, newKey, newValue);
            ////// Save the changes in App.config file.      
            config.Save(ConfigurationSaveMode.Modified);

            ////// Force a reload of a changed section.      
            
////ConfigurationManager.RefreshSection("appSettings");
        }

 

删除 appSettings的一个或多个节点
        /// <summary>
        
/// 删除 appSettings的一个节点。
        
/// </summary>
        
/// <param name="config"></param>
        
/// <param name="key"></param>
        public static void RemoveAppSettingsItemValue(this Configuration config, string key)
        {
            config.AppSettings.Settings.Remove(key);
            config.Save(ConfigurationSaveMode.Modified);
        }

        /// <summary>
        
/// 删除 appSettings的多个节点
        
/// </summary>
        
/// <param name="config"></param>
        
/// <param name="keys"></param>
        public static void RemoveAppSettingsItems(this Configuration config, string[] keys)
        {
            foreach(string key in keys)
                config.AppSettings.Settings.Remove(key);
            config.Save(ConfigurationSaveMode.Modified);
        }

 

增加或appSettings配置节增加多对键、值对
        /// <summary>
        
///更新在config文件中appSettings配置节增加多对键、值对。
        
/// </summary>
        
/// <param name="config"></param>
        
/// <param name="items"></param>
        public static void UpdateAppSettings(this Configuration config, Dictionary<stringstring> items)
        {
            foreach (string key in items.Keys)
            {
                UpdateAppSettingsItemNoSave(config, key, items[key]);
            }
            config.Save(ConfigurationSaveMode.Modified);
        }

        private static void UpdateAppSettingsItemNoSave(Configuration config, string newKey, string newValue)
        {
            bool isModified = false;
            foreach (KeyValueConfigurationElement key in config.AppSettings.Settings)
            {
                if (key.Key == newKey)
                { isModified = true; }
            }

            // You need to remove the old settings object before you can replace it      
            if (isModified)
            { config.AppSettings.Settings.Remove(newKey); }

            // Add an Application Setting.      
            config.AppSettings.Settings.Add(newKey, newValue);
        }

 

以上是对connectionStrings 和 appSetting配置节的一些操作,较多的参考网上资源。

对于DictionarySectionHandler 、NameValueFileSectionHandler 、SingleTagSectionHandler的实现真的不是很多操作,但还是实现了DictionarySectionHandler 、NameValueFileSectionHandler ,至于SingleTagSectionHandler有待进一步实现,或有哪位仁兄实现了,可以回复,谢谢!

 

通用获取key-value 键值对Section值的集合
        /// <summary>
        
/// 通用获取key-value 键值对Section值的集合,可用于DictionarySectionHandler或NameValueSectionHandler 定义的配置节 NameValueSectionHandler的Key值不能重复
        
/// </summary>
        
/// <param name="sectionName"></param>
        
/// <param name="config"></param>
        
/// <returns>没有配置节时返回null</returns>
        public static Dictionary<stringstring> GetKeyValueSectionValues(this Configuration config, string sectionName)
        {
            ////KeyValueConfigurationSection appSettings = (KeyValueConfigurationSection)config.GetSection(sectionName);
            var section = config.GetSection(sectionName);

            if (section == null)
                return null;

            Dictionary<stringstring> result = new Dictionary<stringstring>();

            XmlDocument xdoc = new XmlDocument();
            xdoc.LoadXml(section.SectionInformation.GetRawXml());
            System.Xml.XmlNode xnode = xdoc.ChildNodes[0];

            IDictionary dict = (IDictionary)(new DictionarySectionHandler().Create(nullnull, xnode));
            foreach (string str in dict.Keys)
            {
                result[str] = (string)dict[str];
            }

            return result;
        }

 

由于Framework框架没有提供DictionarySection的节点类,不能直接解释出节点中的元素,因些只能使用XML,通过IConfigurationSectionHandler.Create接口,即DictionarySectionHandler().Create方法,实现了元素的集合。

 

获取子节点为key-value 键值对的值
        /// <summary>
        
/// 获取子节点为key-value 键值对的值,可用于DictionarySectionHandler或NameValueSectionHandler 定义的配置节
        
/// 
        
/// </summary>
        
/// <param name="sectionName">定点名称</param>
        
/// <param name="key">key 的值,不存在的Key值将返回空</param>
        
/// <param name="config">打开的配置文件。</param>
        
/// <returns></returns>
        public static string GetKeyValueSectionItemValue(this Configuration config, string sectionName, string key)
        {
            var section = config.GetSection(sectionName).SectionInformation;
            if (section == null)
                return null;

            XmlDocument xdoc = new XmlDocument();
            xdoc.LoadXml(section.GetRawXml());
            System.Xml.XmlNode xnode = xdoc.ChildNodes[0];

            IDictionary dict = (IDictionary)(new DictionarySectionHandler().Create(nullnull, xnode));
            if (dict.Contains(key))
                return (string)dict[key];
            else
                return null;
        }

 

 

更新配置节,相同的就修改,没有的就增加。
        /// <summary>
        
/// 更新配置节,相同的就修改,没有的就增加。
        
/// </summary>
        
/// <param name="config"></param>
        
/// <param name="sectionName"></param>
        
/// <param name="items"></param>
        public static void UpdateKeyValueSectionValues(this Configuration config, string sectionName, Dictionary<stringstring> items)
        {
            Dictionary<stringstring> orgItem = GetKeyValueSectionValues(config, sectionName);
            if (orgItem == null)
                orgItem = new Dictionary<stringstring>();
            foreach (string key in items.Keys)
            {
                orgItem[key] = items[key];
            }
            UpdateKeyValueSection(config, sectionName, orgItem);
        }

        private static void UpdateKeyValueSection(Configuration config, string sectionName, Dictionary<stringstring> items)
        {
            config.Sections.Remove(sectionName);

            AppSettingsSection section = new AppSettingsSection();
            config.Sections.Add(sectionName, section);

            foreach (string key in items.Keys)
            {
                section.Settings.Add(new KeyValueConfigurationElement(key, items[key]));
            }
            section.SectionInformation.Type = typeof(DictionarySectionHandler).AssemblyQualifiedName;
            config.Save(ConfigurationSaveMode.Modified);
        }

 

更新配置节在这里使用欺骗的做法,我们使用一个AppSettingsSection 配置节类,把Dictionary的键值对作为KeyValueConfigurationElement元素加入到AppSettingsSection 的Settings集合里,在序列化到Config文件前,把section.SectionInformation.Type 更改为typeof(DictionarySectionHandler).AssemblyQualifiedName的字符串,保存后,我们就可以得到一个DictionarySectionHandler的配置节了,些方法很好地解决了序列化的问题。

 

删除配置点的一些配置。
        /// <summary>
        
/// 删除配置点的一些配置。
        
/// </summary>
        
/// <param name="config"></param>
        
/// <param name="sectionName"></param>
        
/// <param name="items"></param>
        public static void RemoveKeyValueSectionValues(this Configuration config, string sectionName, Dictionary<stringstring> items)
        {
            Dictionary<stringstring> orgItem = GetKeyValueSectionValues(config, sectionName);
            if (orgItem != null)
            {
                foreach (string key in items.Keys)
                {
                    orgItem.Remove(key);
                }
                UpdateKeyValueSection(config, sectionName, orgItem);
            }
        }

 

 

        /// <summary>
        
/// 删除配置节。
        
/// </summary>
        
/// <param name="config"></param>
        
/// <param name="sectionName"></param>
        public static void RemoveSection(this Configuration config, string sectionName)
        {
            config.Sections.Remove(sectionName);
            config.Save(ConfigurationSaveMode.Modified);
        }

 

以上的方法全部完成了配置节的增删改,对于配置节组,由于较少使用,暂时不想去完善了,而且一个组其实可以看作是多个单独配置节的组合,意义不大。

 

下面提供一个懒人的方法,就是使用抽象类的静态属性,来自动获取配置的方法(静态属性的名称和配置的key值得相同),至于自动保存和自动取配置节的方法,大家就出点力吧,在些就不提供了。

        /// <summary>
        /// 获取appSettings的配置值。Key值 和 T 的静态属性相同才能取出来。
        /// </summary>
        /// <param name="config">打开的配置实例</param>
        /// <typeparam name="T">要取值的类,类的静态属性要和Key值对应</typeparam>
        public static void GetAppSettingsConfigValue<T>(this Configuration config) where T : class
        {
            //通过反射自动值,增加属性只需把配置的key值和属性的名称相同即可。
            try
            {
                ////Type cfgType = typeof(ConfigUtility);

                ////MethodInfo getAppConfigMethod = cfgType.GetMethod("GetAppConfig", BindingFlags.Static | BindingFlags.Public);
                Type etyType = typeof(T);
                foreach (PropertyInfo pinfo in etyType.GetProperties(BindingFlags.Static | BindingFlags.Public))
                {
                    string keyName = pinfo.Name;
                    string rslt = GetAppSettingsItemValue(config, keyName);
                    Type dType = pinfo.DeclaringType;
                    if (pinfo.PropertyType.IsValueType)
                    {
                        //类型转换
                        if (!String.IsNullOrEmpty(rslt))
                        {
                            try
                            {
                                MethodInfo minfo = pinfo.PropertyType.GetMethod("Parse", new Type[] { typeof(string) });
                                if (minfo != null)
                                {
                                    pinfo.SetValue(null, minfo.Invoke(null, new object[] { rslt }), null);
                                }
                            }
                            catch (System.Exception ex)
                            {
                                Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
                            }
                        }
                    }
                    else
                        pinfo.SetValue(null, rslt, null);
                }
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
            }
        }

 

获取Configuration实例:

            string m_curPath = AppDomain.CurrentDomain.BaseDirectory;
            m_ConfigFullName = Path.Combine(m_curPath, "GlobalSetup.config");
            ExeConfigurationFileMap configFile = new ExeConfigurationFileMap();
            configFile.ExeConfigFilename = m_ConfigFullName;
            Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configFile, ConfigurationUserLevel.None);

整个文档就说到些,希望大家有新的想法就回复,多谢!

 

后续增加对 SingleTagSection 的访问

 

        /// <summary>
        /// 获取SingleTagSectionHandler某节点的值。
        /// </summary>
        /// <param name="config"></param>
        /// <param name="sectionName"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        public static  string GetSingleTagSectionItemValue(this Configuration config, string sectionName, string property)
        {
            Dictionary<string, string> dict = GetSingleTagSectionValues(config, sectionName);
            if (dict != null && dict.Count > 0)
            {
                if (dict.ContainsKey(property))
                    return (string)dict[property];
            }
            return null;
        }

        /// <summary>
        /// 获取SingleTagSectionHandler节点的值。
        /// </summary>
        /// <param name="config"></param>
        /// <param name="sectionName"></param>
        /// <returns></returns>
        public static Dictionary<string, string> GetSingleTagSectionValues(this Configuration config, string sectionName)
        {
            var section = config.GetSection(sectionName);
            if (section == null || section.SectionInformation == null)
                return null;
            ConfigXmlDocument xdoc = new ConfigXmlDocument();
            xdoc.LoadXml(section.SectionInformation.GetRawXml());
            System.Xml.XmlNode xnode = xdoc.ChildNodes[0];

            Dictionary<string, string> result = new Dictionary<string, string>();
            IDictionary dict = (IDictionary)(new SingleTagSectionHandler().Create(null, null, xnode));
            foreach (string str in dict.Keys)
            {
                result[str] = (string)dict[str];
            }

            return result;
        }


        /// <summary>
        /// 更新配置节,相同的就修改,没有的就增加。
        /// </summary>
        /// <param name="config"></param>
        /// <param name="sectionName"></param>
        /// <param name="items"></param>
        public static void UpdateSingleTagSectionValues(this Configuration config, string sectionName, Dictionary<string, string> items)
        {
            Dictionary<string, string> orgItem = GetSingleTagSectionValues(config, sectionName);
            if (orgItem == null)
                orgItem = new Dictionary<string, string>();
            foreach (string key in items.Keys)
            {
                orgItem[key] = items[key];
            }
            UpdateSingleTagSection(config, sectionName, orgItem);
        }

        /// <summary>
        /// 删除配置点的一些配置。
        /// </summary>
        /// <param name="config"></param>
        /// <param name="sectionName"></param>
        /// <param name="items"></param>
        public static void RemoveSingleTagSectionValues(this Configuration config, string sectionName, Dictionary<string, string> items)
        {
            Dictionary<string, string> orgItem = GetSingleTagSectionValues(config, sectionName);
            if (orgItem != null)
            {
                foreach (string key in items.Keys)
                {
                    orgItem.Remove(key);
                }
                UpdateSingleTagSection(config, sectionName, orgItem);
            }
        }


        private static void UpdateSingleTagSection(Configuration config, string sectionName, Dictionary<string, string> items)
        {
            config.Sections.Remove(sectionName);

            DefaultSection section = new DefaultSection();
            config.Sections.Add(sectionName, section);
            ConfigXmlDocument xdoc = new ConfigXmlDocument();
            XmlNode secNode = xdoc.CreateNode(XmlNodeType.Element, sectionName, xdoc.NamespaceURI);
            xdoc.AppendChild(secNode);
            foreach (string key in items.Keys)
            {
                XmlAttribute attr = xdoc.CreateAttribute(key);
                attr.Value = items[key];
                secNode.Attributes.Append(attr);
            }
            section.SectionInformation.SetRawXml(xdoc.OuterXml);
            section.SectionInformation.Type = typeof(SingleTagSectionHandler).AssemblyQualifiedName;
            config.Save(ConfigurationSaveMode.Modified);
        }

 

 

 C# 动态修改配置文件 http://www.cnblogs.com/Yjianyong/archive/2011/10/27/2226429.html   

  C# 动态修改配置文件下篇:http://www.cnblogs.com/Yjianyong/archive/2011/10/28/2227924.html

 

posted @ 2011-10-27 14:42  Lance Yang  阅读(11850)  评论(7编辑  收藏  举报