/// <summary> /// Converts the specified <paramref name="obj"/> to a collection. /// If the object supports the interface <see cref="ICollection"/> itself, /// it will simply be casted. If it is an <see cref="IEnumerable"/>, its contents /// will be copied into a new object implementing <see cref="ICollection"/>. /// Else, a new <see cref="ICollection"/> will be created with <paramref name="obj"/> /// as single contents. /// A string won't be treated as a collection of characters but will be treated as if /// it was no collection. /// </summary> /// <param name="obj">The object to convert to a collection.</param> /// <param name="entryType">Type to convert the collection entries to or <c>null</c>.</param> /// <param name="result">Collection containing the contents of obj or obj itself.</param> /// <returns><c>true</c>, if the conversion was successful, else <c>false</c>.</returns> protected static bool ToCollection(object obj, Type entryType, out ICollection result) { obj = ParserHelper.UnwrapIncludesAndCleanup(obj); if (obj.GetType() != typeof(string)) // Don't treat strings as a collection of characters { if (obj is ICollection) { return(ConvertEntryType((ICollection)obj, entryType, out result)); } if (obj is IEnumerable) { List <object> col = ((IEnumerable)obj).Cast <object>().ToList(); return(ConvertEntryType(col, entryType, out result)); } } List <object> res = new List <object>(); object o2; if (entryType == null) { res.Add(obj); } else if (Convert(obj, entryType, out o2)) { res.Add(o2); } else { result = null; return(false); } result = res; return(true); }
/// <summary> /// Parses the XAML file associated with this parser. /// </summary> /// <returns>The visual corresponding to the root XAML element.</returns> public object Parse() { if (_rootObject != null) { throw new XamlParserException("XAML Parser: Parse() method was invoked multiple times"); } object key; _rootObject = ParserHelper.UnwrapIncludesAndCleanup(Instantiate(_xmlDocument.DocumentElement, out key)); if (key != null) { throw new XamlParserException("A 'x:Key' attribute is not allowed at the XAML root element"); } foreach (EvaluatableMarkupExtensionActivator activator in _deferredMarkupExtensionActivations) { activator.Activate(); } return(_rootObject); }
/// <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<object></c> or an <c>IDictionary<object, object></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)); }