• 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

  • 相关阅读:
    使用IntelliJ IDEA配置Tomcat(入门)
    关于hive异常:Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStor
    完整过程解决 ERROR 1045 (28000): Access denied for user 'mysql'@'localhost' (using password: NO)
    Hadoop伪分布式配置
    Spark_scala_Maven项目创建
    Spark-WordCount
    tesseract-ocr的安装及使用
    解决selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in P
    python第三方库资源
    kafka伪分布式配置
  • 原文地址:https://www.cnblogs.com/Yjianyong/p/2226429.html
Copyright © 2020-2023  润新知