.NET Core采用的全新配置系统[9]: 为什么针对XML的支持不够好?
物理文件是我们最常用到的原始配置的载体,最佳的配置文件格式主要由三种,它们分别是JSON、XML和INI,对应的配置源类型分别是JsonConfigurationSource、XmlConfigurationSource和IniConfigurationSource。但是对于.NET Core的配置系统来说,我们习以为常的XML反倒不是理想的配置源,至少和JSON比较起来,它具有一个先天不足的劣势,那就是针对集合数据结构的支持不如人意。[ 本文已经同步到《ASP.NET Core框架揭秘》之中] 一、为什么针对集合的配置难以通过优雅的XML来表示在《配置模型设计详解》一文中我们对配置模型的设计和实现进行了详细介绍。在此文中我们说应用中的配置体现为一种树形化的层次结构,所我将它称为“配置树”,具体的配置数据通过配置树的“叶子节点”承载。当配置数据从不同的来源加载之后都会转换成一个字典,我将其称为“配置字典”。为了让“配置字典”能够存储“配置树”的所有数据和自身结构,我们需要在配置字典中存储所有叶子节点,叶子节点的路径和值将直接作为字典元素的Key和Value。由于字典的Key是唯一的,这就要求配置树中的每一个节点必须具有唯一的路径。XmlConfigurationSource/XmlConfigurationProvider不能很好地支持集合数据结构的问题就出现在这里。 1: public class Profile 2: {
3: public Gender Gender { get; set; } 4: int Age { get; set; } 5: public ContactInfo ContactInfo { get; set; } 6: }
7:?
8: class ContactInfo 9: {
10: string EmailAddress { get; set; } 11: string PhoneNo { get; set; } 12: }
13:?
14: enum Gender 15: {
16: Male,
17: Female
18: }
举个简单的例子,假设需要采用XML来表示一个Profile对象的集合(Profile的类型具有如上所示的定义),那么我们很自然地会采用如下的结构。 2: Profile Gender="Male" Age="18"ContactInfo EmailAddress ="foobar@outlook.com" PhoneNo="123"/>
class ExtendedXmlConfigurationProvider : XmlConfigurationProvider 4: {} override void Load(Stream stream)
8: //加载源文件并创建一个XmlDocument
10: sourceDoc.Load(stream); 12: //添加索引
14:? 16: XmlDocument newDoc = 17: XmlElement documentElement = newDoc.CreateElement(sourceDoc.DocumentElement.Name);
19:?
20: foreach (XmlElement element in sourceDoc.DocumentElement.ChildNodes) 21: {
22: this.Rebuild(element,documentElement,1)'> 23: name => newDoc.CreateElement(name)); 24: }
25:?
26: //根据新的XmlDocument初始化配置字典 27: using (Stream newStream = new MemoryStream()) 28: {
29: using (XmlWriter writer = XmlWriter.Create(newStream)) 30: {
31: newDoc.WriteTo(writer);
32: }
33: newStream.Position = 0;
34: base.Load(newStream); 35: }
36: }
37:?
38: private void AddIndexes(XmlElement element) 39: {
40: if (element.ChildNodes.OfType<XmlElement>().Count() > 1) 41: {
42: if (element.ChildNodes.OfType<XmlElement>().GroupBy(it => it.Name).Count() == 1) 43: {
44: int index = 0; 45: foreach (XmlElement subElement in element.ChildNodes) 46: {
47: subElement.SetAttribute("append_index",(index++).ToString()); 48: AddIndexes(subElement);
49: }
50: }
51: }
52: }
53:?
54: void Rebuild(XmlElement source,XmlElement destParent,Func<string,XmlElement> creator) 55: {
56: string index = source.GetAttribute("append_index"); 57: string elementName = string.IsNullOrEmpty(index) ? source.Name : $"{source.Name}_index_{index}"; 58: XmlElement element = creator(elementName);
59: destParent.AppendChild(element);
60: foreach (XmlAttribute attribute in source.Attributes) 61: {
62: if (attribute.Name != "append_index") 63: {
64: element.SetAttribute(attribute.Name,attribute.Value);
65: }
66: }
67:?
68: in source.ChildNodes) 69: {
70: Rebuild(subElement,element,creator);
71: }
72: }
73: }
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net-mvc-4 – MVC 4 DropDownListFor错误 – 没有具有密
- asp.net-mvc – 如何在视图中获取会话值asp.net核心
- asp.net-mvc – ASP.NET MVC – 本地化路由
- asp-classic – 为什么这个函数与任意数字相比作为空检查?
- asp.net-core – 如何为所有视图设置布局,基类和使用?
- 如何确定ASP.NET站点(IIS)上的用户数量?和他们的信息?
- asp.net – 如何在网格视图中设置样式模板字段(附加aspx页面
- asp.net-core – 删除继承的ASP.NET Core appsettings
- asp.net-mvc – 区域内的Asp.Net MVC IgnoreRoute
- 一个类如何实现两个接口中同名同参数不同返回值的函数
- ASP.Net / C#:替换数据绑定字段中的字符
- .net-core – 用于.NET Core控制台应用程序的ASP
- 如何强制我的ASP.net 2.0应用程序重新编译
- asp.net – IIS 7.0和IIS 7.5之间有什么区别?
- asp.net-mvc – 什么是实例化和配置DbContext在M
- asp.net – 在渲染到位图之前缩放WPF内容
- asp.net-mvc – 在BaseController中获取/设置Htt
- .NET Core的日志[2]:将日志输出到控制台
- asp.net-mvc – ASP.NET MVC4 CustomErrors Defa
- 为什么我得到“线程被中止”在asp.net?