博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# 动态修改配置文件 (二)
阅读量:6307 次
发布时间:2019-06-22

本文共 13737 字,大约阅读时间需要 45 分钟。

上篇

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

 

ExpandedBlockStart.gif
提供二个访问配置文件的静态方法
        
///
 
<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实例

 

 

ExpandedBlockStart.gif
获取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的完全限定名。

 

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

 

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

 

ExpandedBlockStart.gif
自定义配置节
        
///
 
<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就使用静态属性。

 

ExpandedBlockStart.gif
反射获取属性值
        
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等相同,包括大小写。

 

ExpandedBlockStart.gif
使用抽象类的静态属性来取出配置节的值
        
///
 
<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的值,和反过来取得实例的值

 

 

ExpandedBlockStart.gif
辅助方法
        
///
 
<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);
        }

 

 

ExpandedBlockStart.gif
从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);
        }

 

配置节的保存

 

ExpandedBlockStart.gif
保存配置节
        
///
 
<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来创建实例,效率会快点。

 

ExpandedBlockStart.gif
View Code
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----------------

谢谢大家!

 本文出自:

转载于:https://www.cnblogs.com/Yjianyong/archive/2011/10/28/2227924.html

你可能感兴趣的文章
可执行程序找不到lib库地址的处理方法
查看>>
bash数组
查看>>
Richard M. Stallman 给《自由开源软件本地化》写的前言
查看>>
oracle数据库密码过期报错
查看>>
修改mysql数据库的默认编码方式 .
查看>>
zip
查看>>
How to recover from root.sh on 11.2 Grid Infrastructure Failed
查看>>
rhel6下安装配置Squid过程
查看>>
《树莓派开发实战(第2版)》——1.1 选择树莓派型号
查看>>
在 Linux 下使用 fdisk 扩展分区容量
查看>>
结合AlphaGo算法和大数据的量化基本面分析法探讨
查看>>
如何在 Ubuntu Linux 16.04 LTS 中使用多个连接加速 apt-get/apt
查看>>
《OpenACC并行编程实战》—— 导读
查看>>
机器学习:用初等数学解读逻辑回归
查看>>
如何在 Ubuntu 中管理和使用逻辑卷管理 LVM
查看>>
Oracle原厂老兵:从负面案例看Hint的最佳使用方式
查看>>
把自己Github上的代码添加Cocoapods支持
查看>>
C语言OJ项目参考(2493)四则运算
查看>>
零基础入门深度学习(二):神经网络和反向传播算法
查看>>
find和xargs
查看>>