C#操作配置文件

我一般写ini,很少直接操作config,以后还是多按照微软的方式来,下次使用心得贴上与大家一起共享,以下来自网络

 

 

说了对配置文件的修改,基本上都已经是全部了,后来也补充了SingleTagSectionHandler的访问,现在把对SingleTagSectionHandler的写以及一些能偷懒的方法一起说下,希望大家有好东西都能够分享下,有时用到了,就是好东西,不用到就当作是学习吧

 

提供二个访问配置文件的静态方法
        /// <summary>
        /// 打开默认的配置文件.exe.config
        /// </summary>
        /// <returns></returns>
        public static Configuration GetConfiguration()
        {
            return ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
        }

        /// <summary>
        /// 获取指定的配置文件。
        /// </summary>
        /// <param name="configFullPath">配置文件的全名称</param>
        /// <returns></returns>
        public static Configuration GetConfiguration(string configFullPath)
        {
            ExeConfigurationFileMap configFile = new ExeConfigurationFileMap();
            configFile.ExeConfigFilename = configFullPath;
            Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configFile, ConfigurationUserLevel.None);
            return config;
        }
 

通过上两个静态方法可以获取到Configuration实例

 

 

获取SingleTagSectionHandler节点的值的多个方法
        /// <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;
        }
 

更新SingleTagSection只能通过Xml来实现,在些使用了ConfigXmlDocument类,通过更改DefaultSection的SectionInfomation的RawXml来完成,同时更改SectionInformation.Type为SingleTagSectionHandler的完全限定名。

 

更新和删除
        /// <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);
        }
 

应该还得提供一个对自定义的配置节访问和读写的方法,以更好的扩充

 

自定义配置节
        /// <summary>
        /// 获取自定义的配置节。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="config"></param>
        /// <param name="sectionName"></param>
        /// <returns></returns>
        public static T GetCustomSection<T>(this Configuration config, string sectionName) where T : ConfigurationSection
        {
            return (T)config.GetSection(sectionName);
        }

        /// <summary>
        /// 保存自定义配置节。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="config"></param>
        /// <param name="section"></param>
        /// <param name="sectionName"></param>
        public static void SaveCustomSection<T>(this Configuration config, T section, string sectionName) where T : ConfigurationSection
        {
            config.RemoveSection(sectionName);
            config.Sections.Add(sectionName, section);
            config.Save(ConfigurationSaveMode.Modified);
        }
 

    至于配置组,本人觉得用处不大,实现起来也很别扭,所在就不实现了,如果真的是很复杂的配置,建议自己定义一个配置节吧。

    下面一些懒人的方法,本人觉得还是很不错的,至少会省掉不少的开发时间。

通过反射对实体或静态属性进行赋值,在此假设obj如果为null就使用静态属性。

 

反射获取属性值
        private static void SetPropertiesValue(object obj, Dictionary<string, string> items, Type cfgEtyType)
        {
            BindingFlags bf = BindingFlags.Public;
            if (obj == null)
                bf |= BindingFlags.Static;
            else
                bf |= BindingFlags.Instance;

            PropertyInfo[] pinfos = cfgEtyType.GetProperties(bf);

            foreach (PropertyInfo p in pinfos)
            {
                try
                {
                    if (items.ContainsKey(p.Name))
                    {
                        string val = items[p.Name];
                        if (!string.IsNullOrEmpty(val))
                        {
                            if (p.PropertyType.IsEnum)
                            {
                                //判断是否为数字
                                if (isDigital(val))
                                {
                                    p.SetValue(obj, Enum.Parse(p.PropertyType, val, true), null);
                                }
                                else
                                {
                                    //判断是否存在该名称
                                    if (isExistEnumKey(p.PropertyType, val))
                                        p.SetValue(obj, Enum.Parse(p.PropertyType, val, true), null);
                                }
                            }
                            else if (p.PropertyType.IsValueType)   //值类型
                            {
                                MethodInfo minfo = p.PropertyType.GetMethod("Parse", new Type[] { typeof(string) });
                                if (minfo != null)
                                {
                                    p.SetValue(obj, minfo.Invoke(null, new object[] { val }), null);
                                }
                            }
                            else
                                p.SetValue(obj, val, null);
                        }
                        else if (!p.PropertyType.IsEnum && !p.PropertyType.IsValueType)
                            p.SetValue(obj, val, null);
                    }
                }
                catch (System.Exception ex)
                {
                    Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
                }
            }
        }

        /// <summary>
        /// 判断枚举值是否为数字
        /// </summary>
        /// <param name="strValue"></param>
        /// <returns></returns>
        private static bool isDigital(string strValue)
        {
            return Regex.IsMatch(strValue, @"^(\d+)$");
        }

        /// <summary>
        /// 判断是否存在枚举的名称
        /// </summary>
        /// <param name="type"></param>
        /// <param name="keyName"></param>
        /// <returns></returns>
        private static bool isExistEnumKey(Type type, string keyName)
        {
            bool isExist = false;
            foreach (string key in Enum.GetNames(type))
            {
                if (key.Equals(keyName, StringComparison.OrdinalIgnoreCase))
                {
                    isExist = true;
                    break;
                }
            }
            return isExist;
        }
 

动态获取值,在此再次强调,属性值必需和配置节的Key等相同,包括大小写。

 

使用抽象类的静态属性来取出配置节的值
        /// <summary>
        /// 使用反射获取实体配置节的值,实体的静态属性必需和配置的Key相同。
        /// </summary>
        /// <param name="config">打开的配置实例</param>
        /// <typeparam name="T">要取值的类,类的静态属性要和Key值对应</typeparam>
        /// <param name="sectionName">T 对就的配置节的名称</param>
        public static void GetKeyValueSectionConfigValue<T>(this Configuration config, string sectionName) where T : class
        {
            try
            {
                Dictionary<string, string> dict = GetKeyValueSectionValues(config, sectionName);
                Type cfgEtyType = typeof(T);
                SetPropertiesValue(null, dict, cfgEtyType);
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
            }
        }
 

提供几个和Configuration实例无关的辅助方法,但也作为扩展方法来实现,以方便操作,只要由实例和抽象类来获取到HashTable的值,和反过来取得实例的值

 

 

辅助方法
        /// <summary>
        /// 由集合根据字段的属性生成实体。属性名为key,属性值为value。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="config"></param>
        /// <param name="items"></param>
        /// <returns></returns>
        public static T GetConfigEntityByItems<T>(this Configuration config, Dictionary<string, string> items) where T : class
        {
            Type etyType = typeof(T);
            Func<object> func = etyType.CreateInstanceDelegate();
            object ety = func.Invoke();

            SetPropertiesValue(ety, items, etyType);

            return (T)ety;
        }

        /// <summary>
        /// 由实例生成配置的项。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="config">没有实际使用到</param>
        /// <param name="instance"></param>
        /// <returns></returns>
        public static Dictionary<string, string> GetItemsByConfigEntity<T>(this Configuration config, T instance) where T : class
        {
            Type cfgEtyType = typeof(T);
            BindingFlags bf = BindingFlags.Public;
            if (instance == null)
                bf |= BindingFlags.Static;
            else
                bf |= BindingFlags.Instance;
            PropertyInfo[] pinfos = cfgEtyType.GetProperties(bf);
            Dictionary<string, string> dict = new Dictionary<string, string>();

            foreach (PropertyInfo p in pinfos)
            {
                dict[p.Name] = "" + p.GetValue(instance, null);
            }
            return dict;
        }

        /// <summary>
        /// 由类的静态属性生成配置项。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static Dictionary<string, string> GetItemsByClass<T>(this Configuration config) where T : class
        {
            return GetItemsByConfigEntity<T>(config, null);
        }
 

 

从appSettings获取值
        /// <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值和属性的名称相同即可。
            ////Type cfgType = typeof(ConfigUtility);

            ////MethodInfo getAppConfigMethod = cfgType.GetMethod("GetAppConfig", BindingFlags.Static | BindingFlags.Public);
            Type etyType = typeof(T);

            Dictionary<string, string> items = GetAppSettings(config);

            SetPropertiesValue(null, items, etyType);
        }
 

配置节的保存

 

保存配置节
        /// <summary>
        /// 保存 Section 配置的值。保存为DictionarySectionHandler配置节。
        /// </summary>
        /// <param name="config"></param>
        /// <typeparam name="T"></typeparam>
        /// <param name="sectionName"></param>
        public static void SaveKeyValueSectionConfig<T>(this Configuration config, string sectionName) where T : class
        {
            var orgsection = config.GetSection(sectionName);
            if (orgsection != null)
                config.Sections.Remove(sectionName);

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

            Type etyType = typeof(T);
            foreach (PropertyInfo pinfo in etyType.GetProperties(BindingFlags.Static | BindingFlags.Public))
            {
                string keyName = pinfo.Name;
                object objValue = pinfo.GetValue(null, null);
                ////section.Settings.Remove(keyName);
                section.Settings.Add(new KeyValueConfigurationElement(keyName, "" + objValue));
            }
            section.SectionInformation.Type = typeof(DictionarySectionHandler).AssemblyQualifiedName;
            config.Save(ConfigurationSaveMode.Modified);
        }

        /// <summary>
        /// 保存为 AppSettings 配置的值。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public static void SaveAppSettingsConfig<T>(this Configuration config) where T : class
        {
            try
            {
                Type etyType = typeof(T);
                foreach (PropertyInfo pinfo in etyType.GetProperties(BindingFlags.Static | BindingFlags.Public))
                {
                    string keyName = pinfo.Name;

                    object objValue = pinfo.GetValue(null, null);

                    UpdateAppSettingsItemNoSave(config, keyName, "" + objValue);
                }

                config.Save(ConfigurationSaveMode.Modified);
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
            }
        }
 

配置文件修改系列在此告一段落了,再附加上创建实体用到的Type的扩展,是从网络抄摘下来的,在本息用了代替Activator来创建实例,效率会快点。

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace System
{
    public static class TypeExtensions
    {
        public static Func<object> CreateInstanceDelegate(this Type type)
        {
            NewExpression newExp = Expression.New(type);
            Expression<Func<object>> lambdaExp =
                Expression.Lambda<Func<object>>(newExp, null);
            Func<object> func = lambdaExp.Compile();
            return func;
        }

        public static Func<T, object> CreateInstanceDelegate<T>(this Type type)
        {
            Type paramType = typeof(T);
            var construtor = type.GetConstructor(new Type[] { paramType });
            var param = new ParameterExpression[] { Expression.Parameter(paramType, "arg") };

            NewExpression newExp = Expression.New(construtor, param);
            Expression<Func<T, object>> lambdaExp =
                Expression.Lambda<Func<T, object>>(newExp, param);
            Func<T, object> func = lambdaExp.Compile();
            return func;
        }


        public static Func<T1, T2, object> CreateInstanceDelegate<T1, T2>(this Type type)
        {
            var types = new Type[] { typeof(T1), typeof(T2) };
            var construtor = type.GetConstructor(types);
            int i = 0;
            var param = types.Select(t => Expression.Parameter(t, "arg" + (i++))).ToArray();
            NewExpression newExp = Expression.New(construtor, param);
            Expression<Func<T1, T2, object>> lambdaExp = Expression.Lambda<Func<T1, T2, object>>(newExp, param);
            Func<T1, T2, object> func = lambdaExp.Compile();
            return func;
        }

        //以下方法中的Lambda表达式“Expression<Func<object[], object>> ”已经定义参数是object[], 而构造函数的参数却不能自动转化。当使用以下代码作测试,


        //////以下代码有bug!
        ////public static Func<object[], object> CreateInstanceDelegate(this Type type, params  object[] args)
        ////{
        ////    var construtor = type.GetConstructor(args.Select(c => c.GetType()).ToArray());
        ////    var param = buildParameters(args);

        ////    NewExpression newExp = Expression.New(construtor, param);
        ////    Expression<Func<object[], object>> lambdaExp =
        ////        Expression.Lambda<Func<object[], object>>(newExp, param);
        ////    Func<object[], object> func = lambdaExp.Compile();
        ////    return func;
        ////}

        ////static ParameterExpression[] buildParameters(object[] args)
        ////{
        ////    int i = 0;
        ////    List<ParameterExpression> list = new List<ParameterExpression>();
        ////    foreach (object arg in args)
        ////    {
        ////        list.Add(Expression.Parameter(arg.GetType(), "arg" + (i++)));
        ////    }
        ////    return list.ToArray();
        ////}

    }
}
 

-----------------The End----------------

谢谢大家!

 本文出自 Lance Yang

配置文件概述: 应用程序配置文件是标准的XML 文件 XML 标记和属性是区分大小写的 它是可以 按需要更改的 开发人员可以使用配置文件来更改设置 而不必重编译应用程序 配置 文件的根节点是configuration 我们经常访问的是appSettings 它是由 Net 预定义配置 节 我们经常使用的配置文件的架构是象下面的形式 先大概有个印象 通过后面的实 例会有一个比较清楚的认识 下面的“配置节”可以理解为进行配置一个XML 的节点 常见配置文件模式: <configuration> <configSections> 配置节声明区域 包含配置节和命名空间声明 <section> 配置节声明 <sectionGroup> 定义配置节组 <section> 配置节组中的配置节声明 <appSettings> 预定义配置节 <Custom element for configuration section> 配置节设置区域 2 只有appSettings 节的配置文件及访问方法 下面是一个最常见的应用程序配置文件的例子 只有appSettings 节 < xml version "1 0" encoding "utf 8" > <configuration> <appSettings> <add key "connectionstring" value "User ID sa;Data Source ;Password ;Initial C atalog test;Provider SQLOLEDB 1;" > <add key "TemplatePATH" value "Template" > < appSettings> < configuration> 下面来看看这样的配置文件如何方法 string connectionString ConfigurationSettings AppSettings["connectionstring"]; 使用ConfigurationSettings 类的静态属性AppSettings 就可以直接方法配置文件中的配置 信息 这个属性的类型是NameValueCollection 3 自定义配置文件 3 1 自定义配置节 一个用户自定义的配置节 在配置文件中分为两部分:一是在<configSections>< confi gSections>配置节中声明配置节(上面配置文件模式中的“<section>”) 另外是在<confi gSections>< configSections >之后设置配置节(上面配置文件模式中的“<Custom eleme nt for configuration section>”) 有点类似一个变量先声明 后使用一样 声明一个配 置文件的语句如下: <section name " " type " " > <section>:声明新配置节 即可创建新配置节 P> name:自定义配置节的名称 type:自定义配置节的类型 主要包括System Configuration SingleTagSectionHandler S ystem Configuration DictionarySectionHandler System Configuration NameValueSectionHa ndler 不同的type 不但设置配置节的方式不一样 最后访问配置文件操作上也有差异 下面 我们就举一个配置文件的例子 让它包含这三个不同的type < xml version "1 0" encoding "utf 8" > <configuration> <configSections> <section name "Test1" type "System Configuration SingleTagSectionHandler" > <section name "Test2" type "System Configuration DictionarySectionHandler" > <section name "Test3" type "System Configuration NameValueSectionHandler" > < configSections> <Test1 setting1 "Hello" setting2 "World" > <Test2> <add key "Hello" value "World" > < Test2> <Test3> <add key "Hello" value "World" > < Test3> < configuration> 我们对上面的自定义配置节进行说明 在声明部分使用<section name "Test1" type "Sy stem Configuration SingleTagSectionHandler" >声明了一个配置节它的名字叫Test1 类型 为SingleTagSectionHandler 在设置配置节部分使用<Test1 setting1 "Hello" setting2 "World" >设置了一个配置节 它的第一个设置的值是Hello 第二个值是World 当然 还可以有更多 其它的两个配置节和这个类似 下面我们看在程序中如何访问这些自定义的配置节 我们用过ConfigurationSettings 类 的静态方法GetConfig 来获取自定义配置节的信息 public static object GetConfig string sectionName ; 下面是访问这三个配置节的代码: 访问配置节Test1 IDictionary IDTest1 IDictionary ConfigurationSettings GetConfig "Test1" ; string str string IDTest1["setting1"] +" "+ string IDTest1["setting2"]; MessageBox Show str ; 输出Hello World 访问配置节Test1 的方法2 string[] values1 new string[IDTest1 Count]; IDTest1 Values CopyTo values1 0 ; MessageBox Show values1[0]+" "+values1[1] ; 输出Hello World 访问配置节Test2 IDictionary IDTest2 IDictionary ConfigurationSettings GetConfig "Test2" ; string[] keys new string[IDTest2 Keys Count]; string[] values new string[IDTest2 Keys Count]; IDTest2 Keys CopyTo keys 0 ; IDTest2 Values CopyTo values 0 ; MessageBox Show keys[0]+" "+values[0] ; 访问配置节Test3 NameValueCollection nc NameValueCollection ConfigurationSettings GetConfig "Test3" ; MessageBox Show nc AllKeys[0] ToString +" "+nc["Hello"] ; 输出Hello Wor ld 通过上面的代码我们可以看出 不同的type 通过GetConfig 返回的类型不同 具体获得 配置内容的方式也不一样 配置节处理程序 返回类型 SingleTagSectionHandler Systems Collections IDictionary DictionarySectionHandler Systems Collections IDictionary NameValueSectionHandler Systems Collections Specialized NameValueCollection 3 2 自定义配置节组 配置节组是使用<sectionGroup>元素 将类似的配置节分到同一个组中 配置节组声明 部分将创建配置节的包含元素 在<configSections>元素中声明配置节组 并将属于该组 的节置于<sectionGroup>元素中 下面是一个包含配置节组的配置文件的例子: < xml version "1 0" encoding "utf 8" > <configuration> <configSections> <sectionGroup name "TestGroup"> <section name "Test" type "System Configuration NameValueSectionHandler" > < sectionGroup> < configSections> <TestGroup> <Test> <add key "Hello" value "World" > < Test> < TestGroup> < configuration> 下面是访问这个配置节组的代码: NameValueCollection nc NameValueCollection ConfigurationSettings GetConfig "TestGroup Test" ; MessageBox Show nc AllKeys[0] ToString +" "+nc["Hello"] ; 输出Hello Wor ld">配置文件概述: 应用程序配置文件是标准的XML 文件 XML 标记和属性是区分大小写的 它是可以 按需要更改的 开发人员可以使用配置文件来更改设置 而不必重编译应用程序 配置 文件的根节点是configuration 我们经常访问的 [更多]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值