我一般写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();

        ////}

    }

}