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());
        }
Ejemplo n.º 3
0
        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());
            }
        }