YAML是一种更适合人阅读的文件格式,很多大型的项目像Ruby on Rails都选择YAML作为配置文件的格式。如果项目的配置很少,用JSON或YAML没有多大差别。看看rails项目中的配置文件,如果用JSON写试试什么感受吧。

在《实现自己的.NET Core配置Provider之EF》中已经讲过配置的执行流程,这里不再复述,直接动手。

YamlConfigurationProvider

Yaml是基于文件的,可以直接从FileConfigurationProvider继承,在FileConfigurationProvider实现了监控文件变化并自动重新加载的功能。

internal class YamlConfigurationProvider : FileConfigurationProvider{    public YamlConfigurationProvider(FileConfigurationSource source) : base(source)    {}   

    public override void Load(Stream stream)      {        var parser = new YamlConfigurationFileParser();Data = parser.Parse(stream);}
}

YamlConfigurationParser是解析Yaml文件的核心,后面会介绍。

YamlConfigurationSource

internal class YamlConfigurationSource : FileConfigurationSource{    public override IConfigurationProvider Build(IConfigurationBuilder builder)    {EnsureDefaults(builder);        return new YamlConfigurationProvider(this);}
}

YamlConfigurationSource实现父类的Build方法,返回YamlConfigurationProvider

AddYamlFile扩展方法

为添加Yaml配置源增加扩展方法。

public static class YamlConfigurationExtensions{   

 public static IConfigurationBuilder AddYamlFile(this IConfigurationBuilder builder, string path)    {         return AddYamlFile(builder, provider: null, path: path, optional: false, reloadOnChange: false);}         public static IConfigurationBuilder AddYamlFile(this IConfigurationBuilder builder, string path, bool optional)    {              return AddYamlFile(builder, provider: null, path: path, optional: optional, reloadOnChange: false);}          public static IConfigurationBuilder AddYamlFile(this IConfigurationBuilder builder, string path, bool optional, bool reloadOnChange)    {                return AddYamlFile(builder, provider: null, path: path, optional: optional, reloadOnChange: reloadOnChange);}   

    public static IConfigurationBuilder AddYamlFile(this IConfigurationBuilder builder, IFileProvider provider, string path, bool optional, bool reloadOnChange)    {            if (builder == null){                    throw new ArgumentNullException(nameof(builder));}              if (string.IsNullOrEmpty(path)){            throw new ArgumentException(Resources.Error_InvalidFilePath, nameof(path));}        return builder.AddYamlFile(s =>{s.FileProvider = provider;s.Path = path;s.Optional = optional;s.ReloadOnChange = reloadOnChange;s.ResolveFileProvider();});}        internal static IConfigurationBuilder AddYamlFile(this IConfigurationBuilder builder, Action<YamlConfigurationSource> configureSource)    {              var source = new YamlConfigurationSource();configureSource(source);            return builder.Add(source);}
}

YamlConfigurationFileParser

解析Yaml是核心的功能,目前github有开源的C# Yaml项目:YamlDotNet和SharpYaml 。SharpYaml Fork自YamlDotNet,但做了不少改进并支持Yaml1.2,不过需要netstandard1.6+。YamlDotNet支持Yaml1.1,需要netstandard1.3+。我选择的YamlSharp。

Yaml可表示三种类型的数据:Scalar(标量,如字符串、布尔值、整数等)、Sequence(序列,如数组)和Mapping(映射,如字典,键值对等)。

关于Yaml可以参考阮一峰老师的《YAML 语言教程》。

SharpYaml会把Yaml文件转换为树形结构,然后我们只需要把所有的叶子节点的路径作为字典的键,将叶子节点的值作为字典的值存储起来就可以了。

internal class YamlConfigurationFileParser{   

 private readonly IDictionary<string, string> _data = new SortedDictionary<string, string>(StringComparer.Ordinal);   

 private readonly Stack<string> _context = new Stack<string>();    private string _currentPath;    public IDictionary<string, string> Parse(Stream input){_data.Clear();_context.Clear();        var yaml = new YamlStream();yaml.Load(new StreamReader(input));        if (yaml.Documents.Count > 0){            var rootNode = yaml.Documents[0].RootNode;VisitYamlNode("", rootNode);}        return _data;}   

 private void VisitYamlNode(string context, YamlNode node)    {         if (node is YamlScalarNode){VisitYamlScalarNode(context, (YamlScalarNode)node);}              else if (node is YamlMappingNode)           {VisitYamlMappingNode(context, (YamlMappingNode)node);}              else if (node is YamlSequenceNode)        {VisitYamlSequenceNode(context, (YamlSequenceNode)node);}}   

 private void VisitYamlScalarNode(string context, YamlScalarNode node)    {EnterContext(context);         if (_data.ContainsKey(_currentPath)){                   throw new FormatException(string.Format(Resources.Error_KeyIsDuplicated, _currentPath));}_data[_currentPath] = node.Value;ExitContext();}  

  private void VisitYamlMappingNode(string context, YamlMappingNode node)    {EnterContext(context);        foreach (var yamlNode in node.Children){context = ((YamlScalarNode)yamlNode.Key).Value;VisitYamlNode(context, yamlNode.Value);}ExitContext();}   

   private void VisitYamlSequenceNode(string context, YamlSequenceNode node)    {EnterContext(context);           for (int i = 0; i < node.Children.Count; i++){VisitYamlNode(i.ToString(), node.Children[i]);}ExitContext();}   

   private void EnterContext(string context)    {          if (!string.IsNullOrEmpty(context)){_context.Push(context);}_currentPath = ConfigurationPath.Combine(_context.Reverse());}  

   private void ExitContext()          {             if (_context.Any()){_context.Pop();}_currentPath = ConfigurationPath.Combine(_context.Reverse());}
}

最后

本项目已在github上开源,地址:https://github.com/chengxulvtu/Cxlt.Extensions.Configuration

在项目中使用可以执行下面的命令

Install-Package Cxlt.Extensions.Configuration.Yaml

dotnet add package Cxlt.Extensions.Configuration.Yaml

如果这篇文章对你有帮助或有什么问题,欢迎关注“chengxulvtu"公众号。

相关文章:

  • 10分钟就能学会的.NET Core配置

  • 实现自己的.NET Core配置Provider之EF

原文地址:http://www.cnblogs.com/nianming/p/7097338.html

.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

实现自己的.NET Core配置Provider之Yaml相关推荐

  1. 实现自己的.NET Core配置Provider之EF

    <10分钟就能学会.NET Core配置>里详细介绍了.NET Core配置的用法,另外我还开源了自定义的配置Provider:EF配置Provider和Yaml配置Provider.本文 ...

  2. 实现.NET Core配置Provider之EF

    <10分钟就能学会.NET Core配置>里详细介绍了.NET Core配置的用法另外我还开源了自定义的配置ProviderEF配置Provider和Yaml配置Provider.本文先来 ...

  3. 10分钟就能学会的.NET Core配置

    .NET Core为我们提供了一套用于配置的API,它为程序提供了运行时从文件.命令行参数.环境变量等读取配置的方法.配置都是键值对的形式,并且支持嵌套,.NET Core还内建了从配置反序列化为PO ...

  4. 关于Asp.net core配置信息读取的源码分析梳理

    概述 我们都知道asp.net core配置信息的读取离不开IConfigurationSource和IConfigurationProvider这两个类,ConfigurationSource可以提 ...

  5. ASP.NET Core 配置中心

    前言 正如大家所知,在 .NET Core 中配置文件改成了 appsettings.json,表面上和 .NET Framework 的 web.config 或 app.config 好像没有太大 ...

  6. EF Core数据库Provider一览

    当EF Core 1.x系列和2.0版本之间经过重大的重写时,所有EF Core数据库Provider都受到重创.从那时起,各种私人和商业开发团队一直在努力填补这个空白. 正文 当EF Core 1. ...

  7. ASP.NET Core配置Kestrel 网址Urls

    ASP.NET Core中如何配置Kestrel Urls呢,大家可能都知道使用UseUrls() 方法来配置. 今天给介绍全面的ASP.NET Core 配置 Urls,使用多种方式配置Urls. ...

  8. class com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$Text

    运行mapreduce遇到的奇芭的错: java.lang.ClassCastException: classcom.sun.jersey.core.impl.provider.entity.XMLJ ...

  9. ASP.NET Core 配置 - 创建自定义配置提供程序

    ASP.NET Core 配置 - 创建自定义配置提供程序 在本文中,我们将创建一个自定义配置提供程序,从数据库读取我们的配置.我们已经了解了默认配置提供程序的工作方式,现在我们将实现我们自己的自定义 ...

最新文章

  1. C语言学习笔记-3.顺序结构程序设计
  2. 201421440008网络攻防实验三
  3. SQL随机生成6位数字
  4. Git相关命令及用法
  5. 16999元!华为Mate X 5G折叠屏手机正式发布:不愧是限量款
  6. Git的安装以及常用的命令总结
  7. 目标检测数据集制作常用脚本集合
  8. HDU - 2602(动态规划,01背包问题)
  9. vue 登录页面背景 - 动态粒子特效包括vue3使用 (Vue-Particles)
  10. 丹尼斯·里奇的自述简历
  11. 优化数据库的八种经典方式
  12. 免费的网站,堪称神器
  13. Xxx饭堂系统 JAVA+SQL+JDBC完成一个小项目(下篇)
  14. html图片轮播种类,支持4种类型的jQuery轮播图插件EasySlides
  15. 牵手中关村,这里脱胎换骨引凤来
  16. JS 高级(七)ES6解构、class、promise
  17. laravel voyager 安装
  18. 【一起学Rust | 设计模式】习惯语法——使用借用类型作为参数、格式化拼接字符串、构造函数
  19. matlab语言入门
  20. 鸿蒙初判陶熔铁什么意思,六耳猕猴能模仿孙悟空,但为什么也有一根金箍棒?看一看吧...

热门文章

  1. 如何使用CDR智能填充工具
  2. 如何部署同一个Spring boot web 应用到不同的环境
  3. Netty之有效规避内存泄漏
  4. 最具体的历史centos下一个 postfix + extmail + dovecot + maildrop 安装注意事项2014更新...
  5. OpenStack开启亚洲之旅
  6. insert /*+ APPEND */
  7. mac中的放置java类库扩展的位置
  8. 云上“炼”码兵器 GitHub Codespaces
  9. 基于事件驱动架构构建微服务第16部分:Azure Active Directory B2C
  10. 如何评价一个开源项目——协作影响力