实现自己的.NET Core配置Provider之Yaml
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相关推荐
- 实现自己的.NET Core配置Provider之EF
<10分钟就能学会.NET Core配置>里详细介绍了.NET Core配置的用法,另外我还开源了自定义的配置Provider:EF配置Provider和Yaml配置Provider.本文 ...
- 实现.NET Core配置Provider之EF
<10分钟就能学会.NET Core配置>里详细介绍了.NET Core配置的用法另外我还开源了自定义的配置ProviderEF配置Provider和Yaml配置Provider.本文先来 ...
- 10分钟就能学会的.NET Core配置
.NET Core为我们提供了一套用于配置的API,它为程序提供了运行时从文件.命令行参数.环境变量等读取配置的方法.配置都是键值对的形式,并且支持嵌套,.NET Core还内建了从配置反序列化为PO ...
- 关于Asp.net core配置信息读取的源码分析梳理
概述 我们都知道asp.net core配置信息的读取离不开IConfigurationSource和IConfigurationProvider这两个类,ConfigurationSource可以提 ...
- ASP.NET Core 配置中心
前言 正如大家所知,在 .NET Core 中配置文件改成了 appsettings.json,表面上和 .NET Framework 的 web.config 或 app.config 好像没有太大 ...
- EF Core数据库Provider一览
当EF Core 1.x系列和2.0版本之间经过重大的重写时,所有EF Core数据库Provider都受到重创.从那时起,各种私人和商业开发团队一直在努力填补这个空白. 正文 当EF Core 1. ...
- ASP.NET Core配置Kestrel 网址Urls
ASP.NET Core中如何配置Kestrel Urls呢,大家可能都知道使用UseUrls() 方法来配置. 今天给介绍全面的ASP.NET Core 配置 Urls,使用多种方式配置Urls. ...
- class com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$Text
运行mapreduce遇到的奇芭的错: java.lang.ClassCastException: classcom.sun.jersey.core.impl.provider.entity.XMLJ ...
- ASP.NET Core 配置 - 创建自定义配置提供程序
ASP.NET Core 配置 - 创建自定义配置提供程序 在本文中,我们将创建一个自定义配置提供程序,从数据库读取我们的配置.我们已经了解了默认配置提供程序的工作方式,现在我们将实现我们自己的自定义 ...
最新文章
- C语言学习笔记-3.顺序结构程序设计
- 201421440008网络攻防实验三
- SQL随机生成6位数字
- Git相关命令及用法
- 16999元!华为Mate X 5G折叠屏手机正式发布:不愧是限量款
- Git的安装以及常用的命令总结
- 目标检测数据集制作常用脚本集合
- HDU - 2602(动态规划,01背包问题)
- vue 登录页面背景 - 动态粒子特效包括vue3使用 (Vue-Particles)
- 丹尼斯·里奇的自述简历
- 优化数据库的八种经典方式
- 免费的网站,堪称神器
- Xxx饭堂系统 JAVA+SQL+JDBC完成一个小项目(下篇)
- html图片轮播种类,支持4种类型的jQuery轮播图插件EasySlides
- 牵手中关村,这里脱胎换骨引凤来
- JS 高级(七)ES6解构、class、promise
- laravel voyager 安装
- 【一起学Rust | 设计模式】习惯语法——使用借用类型作为参数、格式化拼接字符串、构造函数
- matlab语言入门
- 鸿蒙初判陶熔铁什么意思,六耳猕猴能模仿孙悟空,但为什么也有一根金箍棒?看一看吧...
热门文章
- 如何使用CDR智能填充工具
- 如何部署同一个Spring boot web 应用到不同的环境
- Netty之有效规避内存泄漏
- 最具体的历史centos下一个 postfix + extmail + dovecot + maildrop 安装注意事项2014更新...
- OpenStack开启亚洲之旅
- insert /*+ APPEND */
- mac中的放置java类库扩展的位置
- 云上“炼”码兵器 GitHub Codespaces
- 基于事件驱动架构构建微服务第16部分:Azure Active Directory B2C
- 如何评价一个开源项目——协作影响力