protected internal virtual void SerializeElement(XmlWriter writer) { var elementName = this.ElementProperty != null ? this.ElementProperty.Name : string.Empty; if (!string.IsNullOrEmpty(elementName)) { writer.WriteStartElement(elementName); } object value; var elements = new List <OptionConfigurationElement>(); foreach (var property in this.Properties) { if (typeof(OptionConfigurationElement).IsAssignableFrom(property.Type)) { if (_values.TryGetValue(property, out value)) { elements.Add((OptionConfigurationElement)value); } } else { if (_values.TryGetValue(property, out value)) { writer.WriteStartAttribute(property.Name); writer.WriteString(OptionConfigurationUtility.GetValueString(value, property.Converter)); writer.WriteEndAttribute(); } } } if (elements.Count > 0) { foreach (var element in elements) { element.SerializeElement(writer); } } if (!string.IsNullOrEmpty(elementName)) { writer.WriteEndElement(); } }
protected override string GetElementKey(OptionConfigurationElement element) { var property = OptionConfigurationUtility.GetKeyProperty(element); if (property == null) { throw new OptionConfigurationException(); } var value = element[property]; if (value == null) { throw new OptionConfigurationException(); } return((string)value.ToString()); }
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."); } if (!configuration._sections.TryGet(reader.GetAttribute(XML_PATH_ATTRIBUTE), out var section)) { 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()); } }
/// <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; //反序列化当前元素的Attributes到当前元素的属性集 this.DeserializeAttributes(reader, this); //如果当前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) { //反序列化当前元素中的Attributes到元素属性集中 this.DeserializeAttributes(reader, element); //将当前读取器移动到集合成员元素上 reader.ReadToDescendant(string.IsNullOrWhiteSpace(property.ElementName) ? collection.ElementName : property.ElementName); } } //调用当前配置元素对象的反序列化方法 element.DeserializeElement(reader.ReadSubtree()); } }