Пример #1
0
        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;
                }
            }
        }
Пример #2
0
        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);
        }
Пример #3
0
        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;
                }
            }
        }
Пример #4
0
        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);
        }