[转载]C# 动态修改配置文件

 

 

在做一些数据库应用程序的时候经常遇到动态配置数据库,所以写了一个小程序,利用App.Config动态读写数据库连接字符串,那些还在用Adapter控件的同志们赶紧抛弃吧。

主要实现代码:

代码
using System.Configuration;
using System.Data.OleDb;

//
string strconn = ConfigurationManager.ConnectionStrings["ConnString"].ConnectionString;

//
private void saveConnection(string connstring)
        {
            
//保存连接
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            config.ConnectionStrings.ConnectionStrings.Remove("ConnString");
            ConnectionStringSettings mySettings = new ConnectionStringSettings("ConnString", connstring, "SQLOLEDB");
            config.ConnectionStrings.ConnectionStrings.Add(mySettings);
            config.Save(ConfigurationSaveMode.Modified);
            
// 强制重新载入配置文件的ConnectionStrings配置节
            ConfigurationManager.RefreshSection("ConnectionStrings");
        }

//----------------------------------------------------

 

public class ConfigureAppConfig
    {
        //静态构造,不能实例化
        static ConfigureAppConfig() { }

        /**//// <summary>
        /// 获取AppSettings配置节中的Key值
        /// </summary>
        /// <param name="keyName">Key's name</param>
        /// <returns>Key's value</returns>
        public static string GetAppSettingsKeyValue(string keyName)
        {
            return ConfigurationManager.AppSettings.Get(keyName);
        }

        /**//// <summary>
        /// 获取ConnectionStrings配置节中的值
        /// </summary>
        /// <returns></returns>
        public static string GetConnectionStringsElementValue()
        {
            ConnectionStringSettings settings = System.Configuration.ConfigurationManager.ConnectionStrings["connectionString"];
            return settings.ConnectionString;
        }

        /**//// <summary>
        /// 保存节点中ConnectionStrings的子节点配置项的值
        /// </summary>
        /// <param name="elementValue"></param>
        public static void ConnectionStringsSave(string ConnectionStringsName, string elementValue)
        {
            System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            config.ConnectionStrings.ConnectionStrings["connectionString"].ConnectionString = elementValue;
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("connectionStrings");
        }

        /**//// <summary>
        /// 判断appSettings中是否有此项
        /// </summary>
        private static bool AppSettingsKeyExists(string strKey, Configuration config)
        {
            foreach (string str in config.AppSettings.Settings.AllKeys)
            {
                if (str == strKey)
                {
                    return true;
                }
            }
            return false;
        }

        /**//// <summary>
        /// 保存appSettings中某key的value值
        /// </summary>
        /// <param name="strKey">key's name</param>
        /// <param name="newValue">value</param>
        public static void AppSettingsSave(string strKey, string newValue)
        {
            System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            if (AppSettingsKeyExists(strKey, config))
            {
                config.AppSettings.Settings[strKey].Value = newValue;
                config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("appSettings");
            }
        }
    }
如果你的程序是对其它程序的配置文件进行操作,代码如下:
            ExeConfigurationFileMap filemap = new ExeConfigurationFileMap();
            filemap.ExeConfigFilename = filePath;//配置文件路径
            config = ConfigurationManager.OpenMappedExeConfiguration(filemap, ConfigurationUserLevel.None);

            if (AppSettingsKeyExists("Refresh", config))
            {
                config.AppSettings.Settings["Refresh"].Value = M_TimeRead.ToString();
            }

            if (AppSettingsKeyExists("MachineNo", config))
            {
                config.AppSettings.Settings["MachineNo"].Value = M_MachineNo;

            }
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");

            config.ConnectionStrings.ConnectionStrings["connectionString"].ConnectionString = M_ConnectionString;
            config.Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("connectionStrings");
数据库字符串加密
ExeConfigurationFileMap filemap = new ExeConfigurationFileMap();
            filemap.ExeConfigFilename = Application.ExecutablePath + ".Config"; //filePath;
            config = ConfigurationManager.OpenMappedExeConfiguration(filemap, ConfigurationUserLevel.None);
            //指定我所要的节点
            ConfigurationSection section = config.ConnectionStrings;

            if ((section.SectionInformation.IsProtected == false) && (section.ElementInformation.IsLocked == false))
            {
                //制定节点加密
                section.SectionInformation.ProtectSection(protect);
                //即使没有修改也保存设置
                section.SectionInformation.ForceSave = true;
                //配置文件内容保存到xml
                config.Save(ConfigurationSaveMode.Full);
            }

//----------------------------------------------------

 

 

扩展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<string, string> 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<string, string> GetKeyValueSectionValues(this Configuration config, string sectionName)
        {
            ////KeyValueConfigurationSection appSettings = (KeyValueConfigurationSection)config.GetSection(sectionName);
            var section = config.GetSection(sectionName);

            if (section == null)
                return null;

            Dictionary<string, string> result = new Dictionary<string, string>();

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

            IDictionary dict = (IDictionary)(new DictionarySectionHandler().Create(null, null, 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(null, null, 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<string, string> items)
        {
            Dictionary<string, string> orgItem = GetKeyValueSectionValues(config, sectionName);
            if (orgItem == null)
                orgItem = new Dictionary<string, string>();
            foreach (string key in items.Keys)
            {
                orgItem[key] = items[key];
            }
            UpdateKeyValueSection(config, sectionName, orgItem);
        }

        private static void UpdateKeyValueSection(Configuration config, string sectionName, Dictionary<string, string> 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<string, string> items)
        {
            Dictionary<string, string> 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);
        }
复制代码
 

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

原文地址:https://www.cnblogs.com/fx2008/p/2287793.html