private static void ResolveOptionElement(XmlReader reader, OptionConfiguration configuration) { if (reader == null || reader.NodeType != XmlNodeType.Element || reader.Name != XML_OPTION_ELEMENT) { return; } if (string.IsNullOrWhiteSpace(reader.GetAttribute("path"))) { throw new OptionConfigurationException("The 'path' attribute of option element is empty or unspecified."); } var section = configuration._sections[reader.GetAttribute(XML_PATH_ATTRIBUTE)]; if (section == null) { section = configuration._sections.Add(reader.GetAttribute(XML_PATH_ATTRIBUTE)); } while (reader.Read() && reader.Depth > 1) { if (reader.NodeType != XmlNodeType.Element) { continue; } var typeName = reader.GetAttribute(reader.Name + ".type"); OptionConfigurationElement element = null; if (string.IsNullOrWhiteSpace(typeName)) { element = OptionConfigurationUtility.GetGlobalElement(reader.Name); if (element == null) { throw new OptionConfigurationException(string.Format("The '{0}' is a undeclared option element in the '{1}' file.", reader.Name, configuration._filePath)); } } else { Type type = Type.GetType(typeName, false, true); if (!typeof(OptionConfigurationElement).IsAssignableFrom(type)) { throw new OptionConfigurationException(string.Format("The '{0}' is not a OptionConfigurationElement type, in the '{0}' file.", typeName, configuration._filePath)); } element = (OptionConfigurationElement)Activator.CreateInstance(type); } if (element != null) { //保存当前元素的名称 string elementName = reader.Name; //判断获取的配置项元素是否为配置项集合 var collection = element as OptionConfigurationElementCollection; if (collection == null) { element.DeserializeElement(reader); } else { int depth = reader.Depth; //由于在OptionConfigurationSection中不允许存在默认集合,则此处始终应将读取器移动到其下的子元素的XML节点上 while (reader.Read() && reader.Depth > depth) { if (reader.NodeType == XmlNodeType.Element) { collection.DeserializeElement(reader.ReadSubtree()); } } } //将处理完毕的元素对象加入到当前选项节中 section.Children.Add(elementName, element); } } }
/// <summary> /// 读取选项配置文件中的XML内容。 /// </summary> /// <param name="reader">在选项配置文件中进行读取操作的<seealso cref="System.Xml.XmlReader"/>读取器。</param> protected internal virtual void DeserializeElement(XmlReader reader) { if (reader.ReadState == ReadState.Initial) { if (!reader.Read()) { throw new OptionConfigurationException(); } } OptionConfigurationProperty property; if (reader.NodeType == XmlNodeType.Element) { var elementName = reader.Name; for (int i = 0; i < reader.AttributeCount; i++) { reader.MoveToAttribute(i); //XML特性名中间含点的,并且是以表示是以元素名打头的,则表示为系统内置特性因而无需解析处理 if (reader.Name.StartsWith(elementName + ".")) { continue; } //获取当前XML元素特性对应的配置属性定义项 if (this.Properties.TryGetValue(reader.Name, out property)) { this.SetPropertyValue(property, reader.Value); } else { //执行处理未知的属性反序列化 if (!this.OnDeserializeUnrecognizedAttribute(reader.Name, reader.Value)) { throw new OptionConfigurationException(string.Format("The '{0}' option configuration attribute is unrecognized.", reader.Name)); } } } //将当前读取器移到元素上 reader.MoveToElement(); } //如果当前XML元素是空元素(即其没有子节点的元素),则返回 if (reader.IsEmptyElement) { return; } //定义当前读取器的初始深度 int depth = reader.Depth; //定义当前待解析子元素的当前配置项元素 OptionConfigurationElement element = this; while (reader.Read() && reader.Depth > depth) { if (reader.NodeType != XmlNodeType.Element) { continue; } if (reader.Depth == depth + 1) { element = this; } //如果当前配置项元素是配置集合,则约定当前读取器所处的位置应当处于其下的集合元素的XML节点处 if (typeof(OptionConfigurationElementCollection).IsAssignableFrom(element.GetType())) { //使用当前配置集合来解析当前读取器所处的XML节点内容 element.DeserializeElement(reader.ReadSubtree()); //忽略后续操作,直接进行后续XML内容处理 continue; } //根据当前XML元素名获取对应的配置属性定义项,如果获取失败则获取当前配置项中的默认集合属性定义项 if (!element.Properties.TryGetValue(reader.Name, out property)) { property = OptionConfigurationUtility.GetDefaultCollectionProperty(element.Properties); } //如果对应的配置属性定义项均获取失败则抛出异常 if (property == null) { throw new OptionConfigurationException(string.Format("The '{0}' option configuration element is unrecognized.", reader.Name)); } //获取或创建当前配置属性定义项对应的目标元素对象 element = element.EnsureElementPropertyValue(property); //判断获取的配置项元素是否为配置项集合 var collection = element as OptionConfigurationElementCollection; if (collection != null) { //如果当前配置项集合不是默认集合(即集合有对应的XML节点),则将当前读取器移动到其下的子元素的XML节点上 if (!property.IsDefaultCollection) { reader.ReadToDescendant(string.IsNullOrWhiteSpace(property.ElementName) ? collection.ElementName : property.ElementName); } } //调用当前配置元素对象的反序列化方法 element.DeserializeElement(reader.ReadSubtree()); } }