中国电信网站备案系统,微信小程序模板开发工具,wordpress电影站群,微信公众平台运营中心电话YAML是一种更适合人阅读的文件格式#xff0c;很多大型的项目像Ruby on Rails都选择YAML作为配置文件的格式。如果项目的配置很少#xff0c;用JSON或YAML没有多大差别。看看rails项目中的配置文件#xff0c;如果用JSON写试试什么感受吧。
在《实现自己的.NET Core配置Pro…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, ActionYamlConfigurationSource 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 IDictionarystring, string _data new SortedDictionarystring, string(StringComparer.Ordinal); private readonly Stackstring _context new Stackstring(); private string _currentPath; public IDictionarystring, 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跨平台或扫描二维码关注