今天做一个windows插件式服务程序,插件有时要读取配置文件的设置,但是服务是动态加载到服务上的,没有办法作到动态修改服务的配置文件(app.config)。在.net 2.0中有一个ConfigurationManager类可以方面的读取默认的配置文件,如果要自定义读取配置文件,这个类也提供了方法,如下所示:

var configMap = new ExeConfigurationFileMap { ExeConfigFilename = configFile };
var config = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None);
var configurationSection = config.GetSection(sectionName);
这种获取到的对象只是这个Section的名称和xml内容,这和ConfigurationManager默认方法GetSection获取到的是一个对象,可以进行强制转换成相应的类型相比,十分的不方便。
在不想造轮子想法,在google中搜索了很久也没有找到好的解决方法。最后,还是自己研究解决。
在上面的对象“configurationSection”是一个DefaultSection的类型,它有一个属性SectionInformation,如下所示:
public System.Configuration.SectionInformation SectionInformation { get; }

这个属性包含了从配置文件中读取到的xml信息,其中这个类型一个关键方法:

public string GetRawXml()

用于获取配置中的xml内容,举例如下:

有如下配置文件:
   1: <configuration>
   2:   <configSections>
   3:     <sectionGroup name="WeiboClientSectionGroup">
   4:       <section name="SinaSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
   5:       <section name="QQSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
   6:       <section name="SohuSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
   7:       <section name="NetEaseSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
   8:     </sectionGroup>
   9:     <sectionGroup name="WeiboSectionGroup">
  10:       <section name="SinaSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
  11:       <section name="QQSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
  12:       <section name="SohuSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
  13:       <section name="NetEaseSection" type="System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
  14:     </sectionGroup>
  15:   </configSections>
  16:   <WeiboClientSectionGroup>
  17:     <SinaSection>
  18:       <add key="AccessToken" value=""/>
  19:       <add key="AccessTokenSecret" value=""/>
  20:       <add key="ResultFormat" value="Json"/>
  21:     </SinaSection>
  22:     <!--<QQSection>
  23:       <add key="AccessToken" value=""/>
  24:       <add key="AccessTokenSecret" value=""/>
  25:       <add key="ResultFormat" value="Json"/>
  26:     </QQSection>-->
  27:     <QQSection>
  28:       <add key="AccessToken" value=""/>
  29:       <add key="AccessTokenSecret" value=""/>
  30:       <add key="ResultFormat" value="Json"/>
  31:     </QQSection>
  32:  
  33:     <SohuSection>
  34:       <add key="AccessToken" value=""/>
  35:       <add key="AccessTokenSecret" value=""/>
  36:       <add key="ResultFormat" value="Json"/>
  37:     </SohuSection>
  38:     <NetEaseSection>
  39:       <add key="AccessToken" value=""/>
  40:       <add key="AccessTokenSecret" value=""/>
  41:       <add key="ResultFormat" value="Json"/>
  42:     </NetEaseSection>
  43:   </WeiboClientSectionGroup>
  44:   <WeiboSectionGroup>
  45:     <SinaSection>
  46:       <add key="AppKey" value=""/>
  47:       <add key="AppSecret" value=""/>
  48:       <add key="AuthorizeUri" value="http://api.t.sina.com.cn/oauth/authorize"/>
  49:       <add key="RequestTokenUri" value="http://api.t.sina.com.cn/oauth/request_token"/>
  50:       <add key="AccessTokenUri" value="http://api.t.sina.com.cn/oauth/access_token"/>
  51:       <add key="CallBackUri" value="null"></add>
  52:     </SinaSection>
  53:     <QQSection>
  54:       <add key="AppKey" value=""/>
  55:       <add key="AppSecret" value=""/>
  56:       <add key="AuthorizeUri" value="https://open.t.qq.com/cgi-bin/authorize"/>
  57:       <add key="RequestTokenUri" value="https://open.t.qq.com/cgi-bin/request_token"/>
  58:       <add key="AccessTokenUri" value="https://open.t.qq.com/cgi-bin/access_token"/>
  59:       <add key="CallBackUri" value="null"></add>
  60:     </QQSection>
  61:     <SohuSection>
  62:       <add key="AppKey" value=""/>
  63:       <add key="AppSecret" value=""/>
  64:       <add key="AuthorizeUri" value="http://api.t.sohu.com/oauth/authorize"/>
  65:       <add key="RequestTokenUri" value="http://api.t.sohu.com/oauth/request_token"/>
  66:       <add key="AccessTokenUri" value="http://api.t.sohu.com/oauth/access_token"/>
  67:       <add key="CallBackUri" value="null"></add>
  68:     </SohuSection>
  69:     <NetEaseSection>
  70:       <add key="AppKey" value=""/>
  71:       <add key="AppSecret" value=""/>
  72:       <add key="AuthorizeUri" value="http://api.t.163.com/oauth/authenticate"/>
  73:       <add key="RequestTokenUri" value="http://api.t.163.com/oauth/request_token"/>
  74:       <add key="AccessTokenUri" value="http://api.t.163.com/oauth/access_token"/>
  75:       <add key="CallBackUri" value="null"></add>
  76:     </NetEaseSection>
  77:   </WeiboSectionGroup>
  78: <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration>

我们sectionName=”WeiboSectionGroup/SinaSection”

上面的函数就返回如下字符串:

<SinaSection>
<add key="AppKey" value=""/>
<add key="AppSecret" value=""/>
<add key="AuthorizeUri" value="http://api.t.sina.com.cn/oauth/authorize"/>
<add key="RequestTokenUri" value="http://api.t.sina.com.cn/oauth/request_token"/>
<add key="AccessTokenUri" value="http://api.t.sina.com.cn/oauth/access_token"/>
<add key="CallBackUri" value="null"></add>
</SinaSection>

另外此类型,还有一个Type属性,是字符串类型,如上面的配置,读取出来就是“

System.Configuration.NameValueSectionHandler,System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

根据上面的信息,我们就可以首先使用反射的方式,生成对象NameValueSectionHandler,现调用此对的Create方法进行创建NameValueCollection,如下所示:

private static TReturn LoadSection<TReturn>(SectionInformation information) where TReturn:class
{
string[] strs = information.Type.Split(",".ToCharArray(), 2);
var handler = (IConfigurationSectionHandler)Assembly.Load(strs[1]).CreateInstance(strs[0]);
var doc = new XmlDocument();
doc.LoadXml(information.GetRawXml());
if (handler != null)
return (TReturn)handler.Create(null, null, doc.ChildNodes[0]);
return null;
}

下面提供一个完整的实例:

   1: public abstract class ConfigBase<T> where T:class 
   2:     {
   3:         protected ConfigBase(string sectionName, string configFile)
   4:         {
   5:             if (string.IsNullOrEmpty(configFile))
   6:             {
   7:                 Section = (T)ConfigurationManager.GetSection(sectionName);
   8:             }
   9:             else
  10:             {
  11:                 var configMap = new ExeConfigurationFileMap { ExeConfigFilename = configFile };
  12:                 var config = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None);
  13:                 var configurationSection = config.GetSection(sectionName);
  14:                 if (configurationSection != null)
  15:                 {
  16:                     Section = LoadSection(configurationSection.SectionInformation);
  17:                 }
  18:             }
  19:         }
  20:  
  21:         private static TReturn LoadSection<TReturn>(SectionInformation information) where TReturn:class 
  22:         {
  23:             string[] strs = information.Type.Split(",".ToCharArray(), 2);
  24:             var handler = (IConfigurationSectionHandler)Assembly.Load(strs[1]).CreateInstance(strs[0]);
  25:             var doc = new XmlDocument();
  26:             doc.LoadXml(information.GetRawXml());
  27:             if (handler != null)
  28:                 return (TReturn)handler.Create(null, null, doc.ChildNodes[0]);
  29:             return null;
  30:         }
  31:  
  32:         protected T LoadSection(SectionInformation information)
  33:         {
  34:             return LoadSection<T>(information);
  35:         }
  36:  
  37:         protected T Section { get; private set; }
  38:     }
 

上面是一个抽象类,从上面的类进行继承,就可以实现功能,如下所示:

   1: public class ClientConfig : ConfigBase<NameValueCollection>
   2:     {
   3:         public ClientConfig(WeiboType weiboType)
   4:             : this(weiboType, null)
   5:         {
   6:         }
   7:  
   8:         public ClientConfig(WeiboType weiboType, string configFile)
   9:             : base(string.Format("WeiboClientSectionGroup/{0}Section", weiboType), configFile)
  10:         {
  11:         }
  12:  
  13:         public string AccessToken
  14:         {
  15:             get { return Section["AccessToken"]; }
  16:         }
  17:  
  18:         public string AccessTokenSecret
  19:         {
  20:             get { return Section["AccessTokenSecret"]; }
  21:         }
  22:  
  23:         public ResultFormat ResultFormat
  24:         {
  25:             get { return (ResultFormat)Enum.Parse(typeof(ResultFormat), Section["ResultFormat"]); }
  26:         }
  27:     }
 
 
 
 
 

.net 中读取自定义Config文件的更多相关文章

  1. 【Core】.NET Core中读取App.config配置文件

    1.项目中添加App.config文件 因为.NET Core的项目本质是控制台应用,所以ConfigurationManager的API会去默认读取app.config配置文件,而不是web.con ...

  2. C#Unit单元测试之读取Web.config文件

    长期一来,我们所完成的项目都没有写单元测试,今天我一时兴起,决定给自己写的代码写单元测试,简单的测试代码分分钟完成了,一运行测试,就懵逼了.没能达到我的预期效果,而是出现图1所示错误. 图1:单元测试 ...

  3. matlab中读取txt数据文件(txt文本文档)

    matlab中读取txt数据文件(txt文本文档) 根据txt文档不同种类介绍不同的读取数据方法 一.纯数据文件(没有字母和中文,纯数字) 对于这种txt文档,从matalb中读取就简单多了 例如te ...

  4. C# 操作自定义config文件

    示例文件:DB.config 1.读取 //先实例化一个ExeConfigurationFileMap对象,把物理地址赋值到它的 ExeConfigFilename 属性中: ExeConfigura ...

  5. matlab中读取txt数据文件(转)

    根据txt文档不同种类介绍不同的读取数据方法 一.纯数据文件(没有字母和中文,纯数字) 对于这种txt文档,从matalb中读取就简单多了 例如test.txt文件,内容为“17.901 -1.111 ...

  6. 读取Excel二进制写入DB,并从DB中读取生成Excel文件

    namespace SendMailSMSService { class Program { static void Main(string[] args) { var connString = Sq ...

  7. PCB 电测试--测试点数自动输出到流程指示中(读取TGZ Stephdr文件)

    好不容易实现了 <PCB 无需解压,直接读取Genesis TGZ指定文件 > 正好这里有一项需求:PCB电测试--测试点数自动输出到流程指示中 一.自动输出测试点小结; 1.由于历史原因 ...

  8. Spark- Spark从SFTP中读取zip压缩文件数据做计算

    我们遇到个特别的需求,一个数据接入的流程跑的太慢,需要升级为用大数据方式去处理,提高效率. 数据: 数据csv文件用Zip 压缩后放置在SFTP中 数据来源: SFTP 数据操作: 文件和它的压缩包一 ...

  9. C#窗体中读取修改xml文件

    由于之前没有操作过xml文件,尤其是在窗体中操作xml,脑子一直转不动,而且很抵制去做这个功能,终于还是突破了自己通过查询资料完成了这个功能,在此记录一下自己的成果. 功能说明:程序中存在的xml文件 ...

随机推荐

  1. Centos 7防火墙firewalld开放80端口

    开启80端口 1.firewall-cmd --zone=public --add-port=80/tcp --permanent  出现success表明添加成功 命令含义: --zone #作用域 ...

  2. 手机操控全站仪安卓版 测量员.app

    大家期待已久的智能化全站仪测量功能已经实现了, 简介 测量员是一款运行在智能手机上的测量应用程序,具有计算精确.轻松高效.智能便捷的特点.测量员可以应用在道路.桥梁.铁路.隧道.地铁.市政等工程中,除 ...

  3. parallels无法启动之大乌龙-流水账版

    欢迎访问我的blog:blog.thinkinside.me     早上到公司,像往日一样,开电脑倒茶喝水. 回到座位打开parallels desktop,发现不对,打开PD非常的慢.显示正在初始 ...

  4. 修改windows系統下xampp中apache端口被其他程式占用的問題

    windows 7安裝後啟動xampp, 提示port 443 被其他程式占用. 網上查找解決方案: http://stackoverflow.com/questions/21182512/how-t ...

  5. text .global_start 和_start

    .text定义一个代码段,这是GCC必须的.global_start和_start代码开始地址定义个标记

  6. Rxlifecycle(二):源码解析

    1.结构 Rxlifecycle代码很少,也很好理解,来看核心类. 接口ActivityLifecycleProvider RxFragmentActivity.RxAppCompatActivity ...

  7. android多国语言文件夹文件汇总

    android多国语言文件夹文件汇总如下: 中文(中国):values-zh-rCN 中文(台湾):values-zh-rTW 中文(香港):values-zh-rHK 英语(美国):values-e ...

  8. Kafka - SQL 代码实现

    1.概述 上次给大家分享了关于 Kafka SQL 的实现思路,这次给大家分享如何实现 Kafka SQL.要实现 Kafka SQL,在上一篇<Kafka - SQL 引擎分享>中分享了 ...

  9. freemarker springmvc配置异常

    异常信息 java.lang.IllegalAccessError: tried to access method freemarker.ext.servlet.AllHttpScopesHashMo ...

  10. node-sass 安装卡在 node scripts/install.js 解决办法

    转自:https://segmentfault.com/a/1190000005921721 ======== 7月12日更新 ======== 总的来说就是两种方法解决: SASS_BINARY_S ...