Net Core全局配置读取管理方法ConfigurationManager

最近在学习.Net Core的过程中,发现.Net Framework中常用的ConfigurationManager在Core中竟然被干掉了。

也能理解。Core中使用的配置文件全是Json,不像Framework使用的XML,暂时不支持也是能理解的,但是毕竟全局配置文件这种东西还挺重要的,阅读了一些文章后目前有3个解决方案。

一、引入扩展System.Configuration.ConfigurationManager

这个扩展库可以直接在Nuget中获取。

使用方法和说明见.NET Core 2.0迁移技巧之web.config配置文件

读取的文件类型和方法都跟.Net Framework中一致,而且仅需引入包就可以,瞬间很兴奋有木有!

但是!在使用过过程中发现这个扩展有问题。项目运行过程中需修改我的app.config文件,对我项目中输出的内容没有丝毫影响,Debug发现获取到的值的确没有变化。重启项目都没有用。只有把项目重新编译才好使。

不知道是不是因为我的打开方式不对,但是最终放弃这个方法。

二、引入扩展Microsoft.Extensions.Options.ConfigurationExtensions

这个扩展库也可以直接在Nuget中获取。

使用方法和说明见 ASP.NET Core实现类库项目读取配置文件

这个可以读取application.json中的配置参数,不再使用XML可以说很好的贴近Core的设计理念。

  可惜,这个也有点美中不足的地方。首先跟上面的那个一样,运行时修改json文件读取到的内容不会改变,但是至少重启项目可以修改,这个让我欣慰很多。另外就是,这个方法采用的是反序列化的原理,也就是必须有一个跟配置文件对应的实体类才可以,这个感觉比较鸡肋,放弃。

三、自定义扩展方法

这个是我这次说的重点,要是前面两个方法能满足读者你的需求,那么就没有必要看下去。

废话少说,先上代码:

public class ConfigurationManager
  {
    /// <summary>
    /// 配置内容
    /// </summary>
    private static NameValueCollection _configurationCollection = new NameValueCollection();

    /// <summary>
    /// 配置监听响应链堆栈
    /// </summary>
    private static Stack<KeyValuePair<string, FileSystemWatcher>> FileListeners = new Stack<KeyValuePair<string, FileSystemWatcher>>();

    /// <summary>
    /// 默认路径
    /// </summary>
    private static string _defaultPath = Directory.GetCurrentDirectory() + "\\appsettings.json";

    /// <summary>
    /// 最终配置文件路径
    /// </summary>
    private static string _configPath = null;

    /// <summary>
    /// 配置节点关键字
    /// </summary>
    private static string _configSection = "AppSettings";

    /// <summary>
    /// 配置外连接的后缀
    /// </summary>
    private static string _configUrlPostfix = "Url";

    /// <summary>
    /// 最终修改时间戳
    /// </summary>
    private static long _timeStamp = 0L;

    /// <summary>
    /// 配置外链关键词,例如:AppSettings.Url
    /// </summary>
    private static string _configUrlSection { get { return _configSection + "." + _configUrlPostfix; } }

    static ConfigurationManager()
    {
      ConfigFinder(_defaultPath);
    }

    /// <summary>
    /// 确定配置文件路径
    /// </summary>
    private static void ConfigFinder(string Path)
    {
      _configPath = Path;
      JObject config_json = new JObject();
      while (config_json != null)
      {
        config_json = null;
        FileInfo config_info = new FileInfo(_configPath);
        if (!config_info.Exists) break;

        FileListeners.Push(CreateListener(config_info));
        config_json = LoadJsonFile(_configPath);
        if (config_json[_configUrlSection] != null)
          _configPath = config_json[_configUrlSection].ToString();
        else break;
      }

      if (config_json == null || config_json[_configSection] == null) return;

      LoadConfiguration();
    }

    /// <summary>
    /// 读取配置文件内容
    /// </summary>
    private static void LoadConfiguration()
    {
      FileInfo config = new FileInfo(_configPath);
      var configColltion = new NameValueCollection();
      JObject config_object = LoadJsonFile(_configPath);
      if (config_object == null || !(config_object is JObject)) return;

      if (config_object[_configSection]!=null)
      {
        foreach (JProperty prop in config_object[_configSection])
        {
          configColltion[prop.Name] = prop.Value.ToString();
        }
      }

      _configurationCollection = configColltion;
    }

    /// <summary>
    /// 解析Json文件
    /// </summary>
    /// <param name="FilePath">文件路径</param>
    /// <returns></returns>
    private static JObject LoadJsonFile(string FilePath)
    {
      JObject config_object = null;
      try
      {
        StreamReader sr = new StreamReader(FilePath, Encoding.Default);
        config_object = JObject.Parse(sr.ReadToEnd());
        sr.Close();
      }
      catch { }
      return config_object;
    }

    /// <summary>
    /// 添加监听树节点
    /// </summary>
    /// <param name="info"></param>
    /// <returns></returns>
    private static KeyValuePair<string, FileSystemWatcher> CreateListener(FileInfo info)
    {

      FileSystemWatcher watcher = new FileSystemWatcher();
      watcher.BeginInit();
      watcher.Path = info.DirectoryName;
      watcher.Filter = info.Name;
      watcher.IncludeSubdirectories = false;
      watcher.EnableRaisingEvents = true;
      watcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Size;
      watcher.Changed += new FileSystemEventHandler(ConfigChangeListener);
      watcher.EndInit();

      return new KeyValuePair<string, FileSystemWatcher>(info.FullName, watcher);

    }

    private static void ConfigChangeListener(object sender, FileSystemEventArgs e)
    {
      long time = TimeStamp();
      lock (FileListeners)
      {
        if (time > _timeStamp)
        {
          _timeStamp = time;
          if (e.FullPath != _configPath || e.FullPath == _defaultPath)
          {
            while (FileListeners.Count > 0)
            {
              var listener = FileListeners.Pop();
              listener.Value.Dispose();
              if (listener.Key == e.FullPath) break;
            }
            ConfigFinder(e.FullPath);
          }
          else
          {
            LoadConfiguration();
          }
        }
      }
    }

    private static long TimeStamp()
    {
      return (long)((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds * 100);
    }

    private static string c_configSection = null;
    public static string ConfigSection
    {
      get { return _configSection; }
      set { c_configSection = value; }
    }

    private static string c_configUrlPostfix = null;
    public static string ConfigUrlPostfix
    {
      get { return _configUrlPostfix; }
      set { c_configUrlPostfix = value; }
    }

    private static string c_defaultPath = null;
    public static string DefaultPath
    {
      get { return _defaultPath; }
      set { c_defaultPath = value; }
    }

    public static NameValueCollection AppSettings
    {
      get { return _configurationCollection; }
    }

    /// <summary>
    /// 手动刷新配置,修改配置后,请手动调用此方法,以便更新配置参数
    /// </summary>
    public static void RefreshConfiguration()
    {
      lock (FileListeners)
      {
        //修改配置
        if (c_configSection != null) { _configSection = c_configSection; c_configSection = null; }
        if (c_configUrlPostfix != null) { _configUrlPostfix = c_configUrlPostfix; c_configUrlPostfix = null; }
        if (c_defaultPath != null) { _defaultPath = c_defaultPath; c_defaultPath = null; }
        //释放掉全部监听响应链
        while (FileListeners.Count > 0)
          FileListeners.Pop().Value.Dispose();
        ConfigFinder(_defaultPath);
      }
    }

} 

最开始设计的是采用缓存,每次调用比对文件的修改时间,大小等特征,出现变化从新载入配置。后来发现图样图森破!

C#提供了专门监听文件系统的方法。所以从新设计了监听响应链堆栈来实现。

使用说明:

1、配置节点:

可以直接写在项目默认的配置文件appsettings.json中 格式如下

{
 "AppSettings": {
  "Title": "Test",
  "Version": "1.2.1",
  "AccessToken": "123456@abc.com"
 }
}

保证配置节点AppSettings存在,剩下的就是以Key-Value的形式来写属性,就可以。

2、外部配置文件

像.Net Framework中一样,可以通过外部配置文件来实现。格式如下

{
  "AppSettings.Url": "D:\\test\\app1.json"
}

采用格式是“配置节点名.外链后缀”的形式。可以设计多级外部配置文件,只要发现有外部配置节点就会向下寻找,并监听链上的所有节点文件的变化。

但是需要注意的是:一旦存在外部配置节点,此文件中的配置节点和参数将不再参与解析

3、可配置初始化参数

包括默认文件路径在内的多个参数均可以修改,详情见代码。

修改后需要手动调用RefreshConfiguration方法,以使配置内容生效,有点像事务处理。建议在项目的Startup方法中修改配置方法。

4、使用

跟.Net Framework中一样,直接调用ConfigurationManager.Appsettings["Title"]就可以了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • ASP.NET Core 2.0 WebApi全局配置及日志实例

    最新在将原来写的一些webSerivce转换为WebApi,直接就用了ASP.Net Core 2.0的框架,在使用中,发现的与原有的asp.net不同的地方,通过搜索已经慢慢解决,记录下来备用. 一.全局配置 在asp.net中,全局变更配置写在web.config中,如下所示 <?xml version="1.0"?> <configuration> <connectionStrings> <add name="conn"

  • Net Core全局配置读取管理方法ConfigurationManager

    最近在学习.Net Core的过程中,发现.Net Framework中常用的ConfigurationManager在Core中竟然被干掉了. 也能理解.Core中使用的配置文件全是Json,不像Framework使用的XML,暂时不支持也是能理解的,但是毕竟全局配置文件这种东西还挺重要的,阅读了一些文章后目前有3个解决方案. 一.引入扩展System.Configuration.ConfigurationManager 这个扩展库可以直接在Nuget中获取. 使用方法和说明见.NET Cor

  • Windows Server 2019远程控制的配置与管理方法

    目录 远程控制的配置与管理 1.Windows Server 远程桌面功能 2.远程显示协议(RDP) 3.网路拓扑及说明 4.配置远程桌面服务器 4.1.创建远程访问账户 4.2.开启远程桌面服务 4.3.删除默认账户权限 4.4.验证远程桌面服务 远程控制的配置与管理 1.Windows Server 远程桌面功能 在企业中服务器一般被寄存在专门的IDC机房中,这些机房在固定的地点,可能距离企业距离很远.但是大部分服务器需要定期维护,如果每次维护时,系统管理员都需要到IDC机房中直接操控服务

  • Spring Boot配置读取实现方法解析

    Spring Boot里面所有的配置信息都放在application.properties中,如果我们想读取配置中的值要怎么做呢? 还需要自己写个读取属性文件的工具类吗?完全不要,我们可以通过各种方式来读取里面的值. 当然写工具类也是一种方式,只是太麻烦了,既然Spring Boot中有封装好的实现,为什么不用. Environment方式读取 框架中有一个org.springframework.core.env.Environment类,可以读取application.properties中配

  • .Net Core自定义配置源从配置中心读取配置的方法

    前言 配置,几乎所有的应用程序都离不开它..Net Framework时代我们使用App.config.Web.config,到了.Net Core的时代我们使用appsettings.json,这些我们再熟悉不过了.然而到了容器化.微服务的时代,这些本地文件配置有的时候就不太合适了.当你把本地部署的服务搬到docker上后,你会发现要修改一个配置文件变的非常麻烦.你不得不通过宿主机进入容器内部来修改文件,也许容器内还不带vi等编辑工具,你连看都不能看,改都不能.更别说当你启动多个容器实例来做分

  • Mybatis 创建方法、全局配置教程详解

    总体介绍:MyBatis实际上是Ibatis3.0版本以后的持久化层框架[也就是和数据库打交道的框架]! 和数据库打交道的技术有: 原生的JDBC技术--->Spring的JdbcTemplate技术 这些工具都是提供简单的SQL语句的执行,但是和我们这里学的MyBatis框架还有些不同, 框架是一整套的东西,例如事务控制,查询缓存,字段映射等等. 我们用原生JDBC操作数据库的时候都会经过: 编写sql---->预编译---->设置参数----->执行sql------->

  • ASP.NET Core配置和管理Web主机

    目录 1.前言 2.设置主机 2.1执行下列任务 2.2重写和增强定义的配置 3.主机配置值 3.1应用程序键(名称) 3.2捕获启动错误 3.3内容根 3.4详细错误 3.5环境 3.6HTTPS端口 3.7服务器(Kestrel) URL 4.重写配置 5.管理主机 6.IHostingEnvironment接口 7.IApplicationLifetime接口 8.作用域验证 1.前言 ASP.NET Core应用程序可以配置和启动主机(Host).主机负责应用程序启动和生命周期管理,配置

  • ASP.NET Core MVC 配置全局路由前缀

    ASP.NET Core MVC 配置全局路由前缀 前言 大家好,今天给大家介绍一个 ASP.NET Core MVC 的一个新特性,给全局路由添加统一前缀.严格说其实不算是新特性,不过是Core MVC特有的. 应用背景 不知道大家在做 Web Api 应用程序的时候,有没有遇到过这种场景,就是所有的接口都是以 /api 开头的,也就是我们的api 接口请求地址是像这样的: http://www.example.com/api/order/333 或者是这样的需求 http://www.exa

  • aop注解方式实现全局日志管理方法

    1:日志实体类 public class SysLog { /** */ private Integer id; /** 日志描述*/ private String description; /** 执行的方法*/ private String method; /** 日志类型 0:操作日志:1:异常日志*/ private Integer logType; /** 客户端请求的ip地址*/ private String requestIp; /** 异常代码*/ private String

  • 为ASP.NET Core强类型配置对象添加验证的方法

    前言 本篇博客中,我将描述如何在ASP.NET Core程序启动时,确保强类型配置对象正确的绑定成功.通过使用IStartupFilter接口对象,你可以更早的验证你的配置对象是否绑定了正确的值,并不需要等待程序启动之后的某个时间点再验证. 这里我将简单描述一下ASP.NET Core的配置系统,以及如何使用强类型配置.我将主要描述一下如何去除对IOptions接口的依赖,然后我会描述一下强类型配置对象绑定不正确的问题.最后,我将给出一个在程序启动时验证强类型配置对象的方案. ASP.NET C

随机推荐