Пример #1
0
        /// <summary>
        /// Parses the contents of an <see cref="XmlNode"/> (not the node itself!).
        /// Parsed will be instances of <see cref="XmlAttribute"/> and <see cref="XmlElement"/>.
        /// In case the node is an <see cref="XmlAttribute"/>, its value will be parsed
        /// and returned. This will normally be a string or an instance of a
        /// markup extension. In case the node is an <see cref="XmlElement"/>,
        /// its children will be instantiatedan returned as an <see cref="IList"/> or
        /// an <see cref="IDictionary"/>, depending on whether the elements have a
        /// <c>x:Key</c> attribute associated.
        /// </summary>
        /// <param name="node">The XML node, an <see cref="XmlAttribute"/> or
        /// an <see cref="XmlElement"/>, whose contents should be parsed.</param>
        /// <returns>Parsed value. This is either a string, a markup extension
        /// instance, an <c>IList&lt;object&gt;</c> or an <c>IDictionary&lt;object, object&gt;</c>.</returns>
        protected object ParseValue(XmlNode node)
        {
            if (node is XmlAttribute) // Member attribute
            {
                return(ParseValue(node.Value));
            }
            if (!(node is XmlElement))
            {
                return(null);
            }

            // Handle explicit or implicit (Content) member element
            // Return value's type will be either a dict or a list, depending on contents
            IList <object> resultList = new List <object>();
            IDictionary <object, object> resultDict = new Dictionary <object, object>();

            foreach (XmlNode childNode in node.ChildNodes)
            {
                if (childNode is XmlElement)
                {
                    if (childNode.LocalName.IndexOf('.') != -1) // "." is used as indicator that we have a member declaration
                    // Ignore member assignments here - we focus on our real children
                    {
                        continue;
                    }
                    object key;
                    object value = Instantiate((XmlElement)childNode, out key);
                    if (key == null)
                    {
                        key = GetImplicitKey(value);
                    }
                    IEvaluableMarkupExtension evaluableMarkupExtension = value as IEvaluableMarkupExtension;
                    // Handle the case if a markup extension was instantiated as a child
                    if (evaluableMarkupExtension != null)
                    {
                        evaluableMarkupExtension.Initialize(this);
                        if (!evaluableMarkupExtension.Evaluate(out value))
                        {
                            throw new XamlParserException("Could not evaluate markup extension '{0}'", evaluableMarkupExtension);
                        }
                    }
                    value = ParserHelper.UnwrapIncludesAndCleanup(value);
                    if (key == null)
                    {
                        resultList.Add(value);
                    }
                    else
                    {
                        try
                        {
                            resultDict.Add(key, value);
                        }
                        catch (ArgumentException e)
                        {
                            throw new XamlParserException("Duplicate key '{0}'", e, key);
                        }
                    }
                    // If a key was provided, register the new element in the current context.
                    // This is necessary if the new element should be accessed before all children
                    // here created are added to their target collection.
                    if (key != null)
                    {
                        _elementContextStack.CurrentElementContext.AddKeyedElement(key, value);
                    }
                }
                else if (childNode is XmlText || childNode is XmlCDataSection) // Ignore other XmlCharacterData nodes
                {
                    resultList.Add(((XmlCharacterData)childNode).Data);
                }
            }
            if (resultList.Count > 0 && resultDict.Count > 0)
            {
                throw new XamlBindingException(
                          "Xaml parser parsing Element '{0}': Child elements containing x:Key attributes cannot be mixed with child elements without x:Key attribute",
                          node.Name);
            }

            if (resultDict.Count > 0)
            {
                return(resultDict);
            }
            return(resultList.Count == 0 ? null : (resultList.Count == 1 ? resultList[0] : resultList));
        }