public void Visit(ElementNode node, INode parentNode) { XmlName propertyName; if (TryGetPropertyName(node, parentNode, out propertyName) && propertyName == XmlName._CreateContent) { var s0 = Values[parentNode]; if (s0 is ElementTemplate) { SetTemplate(s0 as ElementTemplate, node); return; } } var parentElement = parentNode as IElementNode; propertyName = XmlName.Empty; //Simplify ListNodes with single elements var pList = parentNode as ListNode; if (pList != null && pList.CollectionItems.Count == 1) { propertyName = pList.XmlName; parentNode = parentNode.Parent; parentElement = parentNode as IElementNode; } var value = Values[node]; if (propertyName != XmlName.Empty || TryGetPropertyName(node, parentNode, out propertyName)) { if (Skips.Contains(propertyName)) { return; } if (parentElement == null) { return; } if (parentElement.SkipProperties.Contains(propertyName)) { return; } var source = Values[parentNode]; ProvideValue(ref value, node, source, propertyName); SetPropertyValue(source, propertyName, value, Context.RootElement, node, Context, node); } else if (IsCollectionItem(node, parentNode) && parentNode is IElementNode) { var source = Values[parentNode]; ProvideValue(ref value, node, source, XmlName.Empty); string contentProperty; Exception xpe = null; var xKey = node.Properties.ContainsKey(XmlName.xKey) ? ((ValueNode)node.Properties[XmlName.xKey]).Value as string : null; //ResourceDictionary if (xpe == null && TryAddToResourceDictionary(source as ResourceDictionary, value, xKey, node, out xpe)) { return; } // Collection element, implicit content, or implicit collection element. if (xpe == null && typeof(IEnumerable).IsAssignableFrom(Context.Types[parentElement]) && Context.Types[parentElement].GetRuntimeMethods().Any(mi => mi.Name == "Add" && mi.GetParameters().Length == 1)) { var addMethod = Context.Types[parentElement].GetRuntimeMethods().First(mi => mi.Name == "Add" && mi.GetParameters().Length == 1); addMethod?.Invoke(source, new[] { value }); return; } if (xpe == null && (contentProperty = GetContentPropertyName(Context.Types[parentElement].GetTypeInfo())) != null) { var name = new XmlName(node.NamespaceURI, contentProperty); if (Skips.Contains(name)) { return; } if (parentElement.SkipProperties.Contains(propertyName)) { return; } SetPropertyValue(source, name, value, Context.RootElement, node, Context, node); return; } if (xpe == null && Context.Types[parentElement].GetRuntimeMethods().Any(mi => mi.Name == "Add" && mi.GetParameters().Length == 1)) { //if there are similar parameters in the function, this will exist issue. var addMethod = Context.Types[parentElement].GetRuntimeMethods().First(mi => mi.Name == "Add" && mi.GetParameters().Length == 1); if (addMethod != null) { addMethod.Invoke(source, new[] { value }); } return; } xpe = xpe ?? new XamlParseException($"Can not set the content of {((IElementNode)parentNode).XmlType.Name} as it doesn't have a ContentPropertyAttribute", node); if (Context.ExceptionHandler != null) { Context.ExceptionHandler(xpe); } throw xpe; } else if (IsCollectionItem(node, parentNode) && parentNode is ListNode) { var source = Values[parentNode.Parent]; ProvideValue(ref value, node, source, XmlName.Empty); var parentList = (ListNode)parentNode; if (Skips.Contains(parentList.XmlName)) { return; } Exception xpe = null; var xKey = node.Properties.ContainsKey(XmlName.xKey) ? ((ValueNode)node.Properties[XmlName.xKey]).Value as string : null; object _; var collection = GetPropertyValue(source, parentList.XmlName, Context, parentList, out _) as IEnumerable; if (collection == null) { xpe = new XamlParseException($"Property {parentList.XmlName.LocalName} is null or is not IEnumerable", node); } if (xpe == null && TryAddToResourceDictionary(collection as ResourceDictionary, value, xKey, node, out xpe)) { return; } MethodInfo addMethod; if (xpe == null && (addMethod = collection.GetType().GetRuntimeMethods().First(mi => mi.Name == "Add" && mi.GetParameters().Length == 1)) != null) { addMethod.Invoke(collection, new[] { Values[node] }); return; } xpe = xpe ?? new XamlParseException($"Value of {parentList.XmlName.LocalName} does not have a Add() method", node); if (Context.ExceptionHandler != null) { Context.ExceptionHandler(xpe); } else { throw xpe; } } }
static IList <KeyValuePair <XmlName, INode> > ParseXamlAttributes(XmlReader reader, out IList <KeyValuePair <string, string> > xmlns) { Debug.Assert(reader.NodeType == XmlNodeType.Element); var attributes = new List <KeyValuePair <XmlName, INode> >(); xmlns = new List <KeyValuePair <string, string> >(); for (var i = 0; i < reader.AttributeCount; i++) { reader.MoveToAttribute(i); //skip xmlns if (reader.NamespaceURI == "http://www.w3.org/2000/xmlns/") { xmlns.Add(new KeyValuePair <string, string>(reader.LocalName, reader.Value)); continue; } var namespaceUri = reader.NamespaceURI; if (reader.LocalName.Contains(".") && namespaceUri == "") { namespaceUri = ((IXmlNamespaceResolver)reader).LookupNamespace(""); } var propertyName = new XmlName(namespaceUri, reader.LocalName); object value = reader.Value; if (reader.NamespaceURI == X2006Uri) { switch (reader.Name) { case "x:Key": propertyName = XmlName.xKey; break; case "x:Name": propertyName = XmlName.xName; break; case "x:Class": case "x:FieldModifier": continue; default: Debug.WriteLine("Unhandled attribute {0}", reader.Name); continue; } } if (reader.NamespaceURI == X2009Uri) { switch (reader.Name) { case "x:Key": propertyName = XmlName.xKey; break; case "x:Name": propertyName = XmlName.xName; break; case "x:TypeArguments": propertyName = XmlName.xTypeArguments; value = TypeArgumentsParser.ParseExpression((string)value, (IXmlNamespaceResolver)reader, (IXmlLineInfo)reader); break; case "x:DataType": propertyName = XmlName.xDataType; break; case "x:Class": case "x:FieldModifier": continue; case "x:FactoryMethod": propertyName = XmlName.xFactoryMethod; break; case "x:Arguments": propertyName = XmlName.xArguments; break; default: Debug.WriteLine("Unhandled attribute {0}", reader.Name); continue; } } var propertyNode = GetValueNode(value, reader); attributes.Add(new KeyValuePair <XmlName, INode>(propertyName, propertyNode)); } reader.MoveToElement(); return(attributes); }
static void ParseXamlElementFor(IElementNode node, XmlReader reader) { Debug.Assert(reader.NodeType == XmlNodeType.Element); var elementName = reader.Name; var isEmpty = reader.IsEmptyElement; if (isEmpty) { return; } while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.EndElement: Debug.Assert(reader.Name == elementName); //make sure we close the right element return; case XmlNodeType.Element: // 1. Property Element. if (reader.Name.Contains(".")) { XmlName name; if (reader.Name.StartsWith(elementName + ".", StringComparison.Ordinal)) { name = new XmlName(reader.NamespaceURI, reader.Name.Substring(elementName.Length + 1)); } else //Attached DP { name = new XmlName(reader.NamespaceURI, reader.LocalName); } var prop = ReadNode(reader); if (prop != null) { node.Properties.Add(name, prop); } } // 2. Xaml2009 primitives, x:Arguments, ... else if (reader.NamespaceURI == X2009Uri && reader.LocalName == "Arguments") { var prop = ReadNode(reader); if (prop != null) { node.Properties.Add(XmlName.xArguments, prop); } } // 3. DataTemplate (should be handled by 4.) else if ((node.XmlType.NamespaceUri == XFUri || node.XmlType.NamespaceUri == NUI2018Uri) && (node.XmlType.Name == "DataTemplate" || node.XmlType.Name == "ControlTemplate")) { var prop = ReadNode(reader, true); if (prop != null) { node.Properties.Add(XmlName._CreateContent, prop); } } // 4. Implicit content, implicit collection, or collection syntax. Add to CollectionItems, resolve case later. else { var item = ReadNode(reader, true); if (item != null) { node.CollectionItems.Add(item); } } break; case XmlNodeType.Whitespace: break; case XmlNodeType.Text: case XmlNodeType.CDATA: if (node.CollectionItems.Count == 1 && node.CollectionItems[0] is ValueNode) { ((ValueNode)node.CollectionItems[0]).Value += reader.Value.Trim(); } else { node.CollectionItems.Add(new ValueNode(reader.Value.Trim(), (IXmlNamespaceResolver)reader)); } break; default: Debug.WriteLine("Unhandled node {0} {1} {2}", reader.NodeType, reader.Name, reader.Value); break; } } }
public static object Create(XmlReader reader, bool doNotThrow = false) { object inflatedView = null; if (reader != null) { while (reader.Read()) { //Skip until element if (reader.NodeType == XmlNodeType.Whitespace) { continue; } if (reader.NodeType == XmlNodeType.XmlDeclaration) { continue; } if (reader.NodeType != XmlNodeType.Element) { Debug.WriteLine("Unhandled node {0} {1} {2}", reader.NodeType, reader.Name, reader.Value); continue; } var rootnode = new RuntimeRootNode(new XmlType(reader.NamespaceURI, reader.Name, null), null, (IXmlNamespaceResolver)reader); XamlParser.ParseXaml(rootnode, reader); var visitorContext = new HydrationContext { ExceptionHandler = doNotThrow ? e => { } : (Action <Exception>)null, }; var cvv = new CreateValuesVisitor(visitorContext); // Visit Parameter Properties to create instance from parameterized constructor var type = XamlParser.GetElementType(rootnode.XmlType, rootnode, null, out XamlParseException xpe); if (xpe != null) { throw xpe; } var ctorInfo = type.GetTypeInfo() .DeclaredConstructors.FirstOrDefault( ci => ci.GetParameters().Length != 0 && ci.IsPublic && ci.GetParameters().All(pi => pi.CustomAttributes.Any(attr => attr.AttributeType == typeof(ParameterAttribute)))); if (ctorInfo != null) { foreach (var parameter in ctorInfo.GetParameters()) { var propname = parameter.CustomAttributes.First(ca => ca.AttributeType.FullName == "Tizen.NUI.Binding.ParameterAttribute")? .ConstructorArguments.First() .Value as string; var name = new XmlName("", propname); if (rootnode.Properties.TryGetValue(name, out INode node) && node is ValueNode) { node.Accept(cvv, rootnode); } } } cvv.Visit((ElementNode)rootnode, null); inflatedView = rootnode.Root = visitorContext.Values[rootnode]; visitorContext.RootElement = inflatedView as BindableObject; Visit(rootnode, visitorContext); break; } } return(inflatedView); }