.NET平台开源项目速览(5)深入使用与扩展SharpConfig组件
.NET开源目录:【目录】本博客其他.NET开源项目文章目录
本文原文地址:.NET平台开源项目速览(5)深入使用与扩展SharpConfig组件
1.SharpConfig源码分析SharpConfig源码并不大,核心代码其实也很简单,就是文件读写,解析。在深入使用和扩展SharpConfig之前,有必要了解一下它的基本结构。所以先来介绍SharpConfig源码中核心的3大类。
Configuration是核心类,我们在前面的文章中只是简单的介绍了一下如何加载配置文件,查看源代码,可以发现加载和保存的方法都是匹配的,都可以从文件或者数据流中加载或者保存。
由于每一个配置文件都包含若干个Section节,所以也可以使用索引来获取这些节,然后操作节下面的设置项。总的来说思路是很简单的。
Configuration在解析过程中,每碰到一个Section,就添加到列表中。而Section的区分就是靠Name,所以,我们在配置文件中注意不要把Section的名称搞混淆了。Section源码中没有特别需要注意的地方,主要是这里检测和移除节点的方法,如下面代码:
1 /// summary 检测节中是否存在某个特定名称的设置 /summary 2 /// param name="settingName" 设置项的名称 /param 3 /// returns True if the setting is contained in the section; false otherwise. /returns 4 public bool Contains(string settingName) 6 return GetSetting(settingName) != null; 9 /// summary 从本节中移除某个名称的设置 /summary 10 public void Remove(string settingName) 12 if (string.IsNullOrEmpty(settingName)) 13 throw new ArgumentNullException("settingName"); 15 var setting = GetSetting(settingName); 17 if (setting == null) 19 throw new ArgumentException("The specified setting does not exist in the section."); 21 mSettings.Remove(setting); 22 }
每一个Section下面可以有多个Setting设置。下面看看Setting类的情况。 Setting主要是获取和设置值的方法,如代码:
var someInteger = section["SomeInteger"].GetValue Boolean (); float someFloat = section["SomeFloat"].GetValue float
什么只是简单的对SharpConfig 的结构做一个分析,下面我们将针对问题进行跟深入的分析和修改。
2.SharpConfig使用问题与扩展 2.1 读取乱码的问题第一次发现这个问题并不是我,是网友在看完我的文章介绍后使用,发现读取出来是乱码,不能解析。然后反馈给我。其实问题很简单,只是我也没有注意,其实读取的时候也多个方法可以选择, 默认使用的是null编码设置,系统自动检测,但这非常不保险。最好还是自己把文件的编码写进去。例如:
Configuration config = Configuration.LoadFromFile("example.ini", Encoding.GetEncoding("gb2312"));
这样修改后,如果配置文件中有中文,一般是没问题的。非常重要的一点,如果你读取的时候用了固定编码,修改配置值需要保存的时候,也一定要加上编码,否则会导致其他的配置都发生乱码的情况。如下面的代码:
config.Save("example.ini", Encoding.GetEncoding("gb2312"));
编码的问题,我们可以看一下源码中的情况:
1 /// summary 从配置文件直接加载,自动检测编码类型,以及使用默认的设置 /summary 2 /// param name="filename" 本地配置文件名称 /param 3 public static Configuration LoadFromFile(string filename) 5 return LoadFromFile(filename, null); 8 /// summary 从配置文件直接加载 /summary 9 /// param name="filename" 本地配置文件名称 /param 10 /// param name="encoding" 文件的编码类型,如果为Null,则自动检测 /param 11 public static Configuration LoadFromFile(string filename, Encoding encoding) 13 if (!File.Exists(filename)) 14 throw new FileNotFoundException("Configuration file not found.", filename); 16 Configuration cfg = null; 18 if (encoding == null) 19 cfg = LoadFromText(File.ReadAllText(filename)); 20 else 21 cfg = LoadFromText(File.ReadAllText(filename, encoding)); 23 return cfg; 24 }2.2 需要赋空值的情况
碰到这个问题,可能有些变态吧。其实并不是一个问题,如果需要是String,建议直接写一个固定的值,在后台读取的时候进行判断,因为SharpConfig处理的时候,会剔除前后的空白字符。所以这种情况你直接给空字符串是不可取 的,给一个 null,然后后台判断是否==null,然后进行对应操作;如果是数值类型,也可以特定的设置一个值,比如为0,转换 的时候 判断是否为0,否则作为空处理。
2.3 #注释符与字符串冲突的问题在SharpConfig中,其实有一个可以定义注释符的地方。
/// summary 获取或者设置 注释标识字符 /summary public static char[] ValidCommentChars get { return mValidCommentChars; } if (value == null) throw new ArgumentNullException("value"); if (value.Length == 0) throw new ArgumentException("The comment chars array must not be empty.","value"); mValidCommentChars = value; }
在配置类的静态构造函数中,默认给了这几个字符作为标识符:
//静态构造函数,设置这些默认值,因此可以修改 static Configuration() mNumberFormat = CultureInfo.InvariantCulture.NumberFormat; mValidCommentChars = new[] { #, ;, \ }; mIgnoreInlineComments = false; mIgnorePreComments = false; }
所以如果配置文件中值可能会出现#号的情况,那你就找一个不出现的 字符,来单独作为你的注释标记符,给这个静态属性赋值即可。
2.4 字符串需要换行的问题这个问题也很有意思。如果是一行固定文本,你放在配置文件,会自动显示换行,但是读取的时候,人家是看做一行的。因为没有换行符结尾。而如果有几段字符,换行符分割开了,这个时候SharpConfig是肯定不支持的,我们可以看一下SharpConfig中核心的解析函数:
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 //根据字符串解析配置文件,核心的解析函数 2 private static Configuration Parse(string source) 4 //重置临时字段 5 mLineNumber = 0; 7 Configuration config = new Configuration(); 8 Section currentSection = null; 9 var preComments = new List Comment (); 11 using (var reader = new StringReader(source)) 13 string line = null; 15 // 读取一行,直到结尾(Read until EOF.) 16 while ((line = reader.ReadLine()) != null) 18 mLineNumber++; 19 //删除前后空白字符 20 line = line.Trim(); 22 //这里扩展核心的换行支持,使用 3个 ... 开头,说明是上一个设置的换行 23 //每一次行都读取下一行试一下,如果有...,就添加 24 if(line.StartsWith("...")) 26 var text = "\r\n" + line.Substring(3); 27 currentSection[currentSection.SettingCount - 1].Value += text; 28 continue; 30 //如果是空行跳过 31 if (string.IsNullOrEmpty(line)) continue; 33 int commentIndex = 0; 34 var comment = ParseComment(line, out commentIndex); 36 if (!mIgnorePreComments commentIndex == 0) 38 // 解析注释行,添加到 注释列表中去 39 preComments.Add(comment); 40 continue; 42 else if (!mIgnoreInlineComments commentIndex 0) 44 // 去掉这一行的注释 45 line = line.Remove(commentIndex).Trim(); 48 //如果开始字符是 [ ,说明是 节(Sections) 49 if (line.StartsWith("[")) 51 #region 节解析 52 currentSection = ParseSection(line); 54 if (!mIgnoreInlineComments) 55 currentSection.Comment = comment; 57 if (config.Contains(currentSection.Name)) 59 throw new ParserException(string.Format( 60 "The section {0} was already declared in the configuration.", 61 currentSection.Name), mLineNumber); 64 if (!mIgnorePreComments preComments.Count 0) 66 currentSection.mPreComments = new List Comment (preComments); 67 preComments.Clear(); 70 config.mSections.Add(currentSection); 71 #endregion 73 else //否则就是键值设置行 75 //解析设置行 76 Setting setting = ParseSetting(line); 78 if (!mIgnoreInlineComments) setting.Comment = comment; 80 if (currentSection == null) throw new ParserException(string.Format("The setting {0} has to be in a section.", setting.Name), mLineNumber); 82 if (currentSection.Contains(setting.Name)) throw new ParserException(string.Format("The setting {0} was already declared in the section.", setting.Name), mLineNumber); 84 if (!mIgnorePreComments preComments.Count 0) 86 setting.mPreComments = new List Comment (preComments); 87 preComments.Clear(); 89 currentSection.Add(setting); 94 return config; 95 }View Code
上面我进行了注释的翻译,从流程可以看到,SharpConfig是依次读取每一行直接进行转换,看看满足什么特征,然后进行处理。如果直接换行,没有Name和=号对应,那会报错。所以我们自己动手,扩展一下,其实非常简单。
上述代码是我已经扩展好的,思路很简单,我们选得一个标记字符串,这里使用“...”作为值换行的标记,每一次读取新行的值后,我们先进行换行判断,如果包含"...",就默认作为当前节最后一个Setting的附加值,手动加上换行符"\r\n"。所以核心的代码其实很简单,主要是你要搞清楚流程,要加在哪里:
//这里扩展核心的换行支持,使用 3个 ... 开头,说明是上一个设置的换行 //每一次行都读取下一行试一下,如果有...,就添加 if(line.StartsWith("...")) var text = "\r\n" + line.Substring(3); currentSection[currentSection.SettingCount - 1].Value += text; continue; }
我们看一个例子,来测试一下换行值的情况,下面是配置文件:
控制台直接读取这个值的代码:
//按文件名称加载配置文件 Configuration config = Configuration.LoadFromFile("example.ini", Encoding.GetEncoding("gb2312")); Section section = config["General"]; string someString = section["SomeString"].Value; Console.WriteLine("字符串SomeString值:{0}", someString);
结果如下,已经默认进行换行了:
现在写博客频繁了,也有大量代码,所以开始使用github,这次就作为我的第一个开源项目代码吧,把我修改后的源码发在上面,大家去下载好了。
另外,我也对SharpConfig进行了翻译,可以便于大家更方便的使用,源码可以去github的地址下载,帮助文档也在里面哦。这里先截个图:
这个帮助文档也是使用:.NET平台开源项目速览(4).NET文档生成工具ADB及使用 文章中的ADB工具来生成的,非常好用。
文档和源码下载地址:https://github.com/asxinyu/Improved_SharpConfig
【C#】.net core2.1,通过扩展状态代码页方法对404页面进行全局捕抓并响应信息 在开发一个网站项目时,除了异常过滤功能模块,还需要有针对404不存在的api接口和页面处理功能 本篇文章就来讲讲,如何自定义全局请求状态类来统一处理
使用.NET Core搭建分布式音频效果处理服务(四)选择垂直扩展还是水平扩展? 众所周知垂直扩展是提升单机的性能的方式,比如提升双路、四路的CPU运算能力,加大内存,更换速度更快的SSD,或者从代码根本上进行优化和性能提升。水平扩展是提供多台多种服务器分离单机性能的方式,比如集群,主从,队列,负载平衡等等。
相关文章
- 使用 Visual Studio 部署 .NET Core 应用 ——.Net Core 部署到SUSE Linux Enterprise Server 12 SP2 64 位(GNOME 版本3.20.2)
- ASP.NET Core中如何更改文件上传大小限制maxAllowedContentLength属性值
- .NET 开源Protobuf-net从入门到精通
- .NET开发中的事务处理大比拼
- .net使用RabbitMQ
- 《ASP.NET MVC4 WEB编程》学习笔记------.net mvc实现原理ActionResult/View
- ASP.NET通过更改Url进行页面传值
- .Net 4.5 异步编程初试(async和await)
- asp.net中Repeater控件用法笔记
- 17+个ASP.NET MVC扩展点,含源码{转}
- [ASP.NET Core 3框架揭秘] 文件系统[4]:程序集内嵌文件系统
- .NET平台开源项目速览(5)深入使用与扩展SharpConfig组件
- Atitit ..Net Framework sdk 3.0 3.5 4.04.5 4.6 4.7 .net core版本新特性 v2 s22 1. 新特性来源于 down ms 官方网站1
- 你的NET程序需要保护吗?Agile.net 6.6.X 注入式Crack
- Spire.Office 7.4.10 for NET is released
- net start mysql 无法启动mysql解决方案之一【NET HELPMSG 3534】
- ASP.NET Core微服务(六)——【.Net Core操作redis】StackExchange.Redis
- 七天来学习ASP.NET MVC (两)——ASP.NET MVC 数据传输
- 解决.NET Framework 3.5 sp1离线安装方案
- .Net Core 商城微服务项目系列(十二):使用k8s部署商城服务
- ASP.NET Core 中间件
- dump文件解析之探索.Net的内存
- ASP.NET Core MVC 之过滤器(Filter)
- VB.net:VB.net编程语言学习之操作符(变量/常量/数据类型/声明)&逻辑控制语句(条件判断/循环语句)的简介、案例应用之详细攻略
- ASP.NET Core微服务(六)——【.Net Core操作redis】StackExchange.Redis
- .net core 3.1 使用 AddJwtBearer 提示未包含AddJwtBearer定义,并找不到扩展方法AddJwtBearer的问题