程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# 動態修改配置文件

C# 動態修改配置文件

編輯: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的功能

 

獲取連接字符串

 

 

        ///<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;

        }

 

 

更新連接字符串

 

 

        ///<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項

 

 

        ///<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的節點

 

 

        /// <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配置節增加一對鍵、值對。

 

 

        ///<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);

        }

 

 

以上的方法全部完成了配置節的增刪改,對於配置節組,由於較少使用,暫時不想去完善了,而且一個組其實可以看作是多個單獨配置節的組合,意義不大。

 

 

 

下面提供一個懶人的方法,就是使用抽象類的靜態屬性,來自動獲取配置的方法(靜態屬性的名稱和配置的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);

 

 

整個文檔就說到些,希望大家有新的想法就回復,多謝!

作者 Lance Yang

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved