public void Visit(ElementNode node, INode parentNode) { foreach (var propertyKvp in node.Properties) { var propertyName = propertyKvp.Key; var propertyValue = (propertyKvp.Value as ValueNode)?.Value as string; if (propertyValue == null) { continue; } if (propertyName.NamespaceURI != "http://schemas.openxmlformats.org/markup-compatibility/2006" || propertyName.LocalName != "Ignorable") { continue; } (parentNode.IgnorablePrefixes ?? (parentNode.IgnorablePrefixes = new List <string>())).AddRange(propertyValue.Split(',')); } foreach (var propertyKvp in node.Properties.ToList()) { // skip d:foo="bar" var prefix = node.NamespaceResolver.LookupPrefix(propertyKvp.Key.NamespaceURI); if (node.SkipPrefix(prefix)) { node.Properties.Remove(propertyKvp.Key); } var propNs = (propertyKvp.Value as IElementNode)?.NamespaceURI ?? ""; var propPrefix = node.NamespaceResolver.LookupPrefix(propNs); if (node.SkipPrefix(propPrefix)) { node.Properties.Remove(propertyKvp.Key); } } foreach (var prop in node.CollectionItems.ToList()) { var propNs = (prop as IElementNode)?.NamespaceURI ?? ""; var propPrefix = node.NamespaceResolver.LookupPrefix(propNs); if (node.SkipPrefix(propPrefix)) { node.CollectionItems.Remove(prop); } } if (node.SkipPrefix(node.NamespaceResolver.LookupPrefix(node.NamespaceURI))) { node.Properties.Clear(); node.CollectionItems.Clear(); } }
public void Visit(ElementNode node, INode parentNode) { foreach (var propertyKvp in node.Properties) { var propertyName = propertyKvp.Key; var propertyValue = (propertyKvp.Value as ValueNode)?.Value as string; if (propertyValue == null) { continue; } if (!propertyName.Equals(XamlParser.McUri, "Ignorable")) { continue; } (parentNode.IgnorablePrefixes ?? (parentNode.IgnorablePrefixes = new List <string>())).AddRange(propertyValue.Split(',')); } foreach (var propertyKvp in node.Properties.ToList()) { // skip d:foo="bar" var prefix = node.NamespaceResolver.LookupPrefix(propertyKvp.Key.NamespaceURI); if (node.SkipPrefix(prefix)) { node.Properties.Remove(propertyKvp.Key); } var propNs = (propertyKvp.Value as IElementNode)?.NamespaceURI ?? ""; var propPrefix = node.NamespaceResolver.LookupPrefix(propNs); if (node.SkipPrefix(propPrefix)) { node.Properties.Remove(propertyKvp.Key); } } foreach (var prop in node.CollectionItems.ToList()) { var propNs = (prop as IElementNode)?.NamespaceURI ?? ""; var propPrefix = node.NamespaceResolver.LookupPrefix(propNs); if (node.SkipPrefix(propPrefix)) { node.CollectionItems.Remove(prop); } } if (node.SkipPrefix(node.NamespaceResolver.LookupPrefix(node.NamespaceURI))) { node.Properties.Clear(); node.CollectionItems.Clear(); } }
public void Visit(ElementNode node, INode parentNode) { if (node.SkipPrefix(node.NamespaceResolver.LookupPrefix(node.NamespaceURI))) return; var value = Values[node]; var parentElement = parentNode as IElementNode; var markupExtension = value as IMarkupExtension; var valueProvider = value as IValueProvider; if (markupExtension != null) { var serviceProvider = new XamlServiceProvider(node, Context); value = markupExtension.ProvideValue(serviceProvider); } if (valueProvider != null) { var serviceProvider = new XamlServiceProvider(node, Context); value = valueProvider.ProvideValue(serviceProvider); } XmlName propertyName; if (TryGetPropertyName(node, parentNode, out propertyName)) { if (Skips.Contains(propertyName)) return; if (parentElement.SkipProperties.Contains(propertyName)) return; var source = Values[parentNode]; if (propertyName == XmlName._CreateContent && source is ElementTemplate) SetTemplate(source as ElementTemplate, node); else SetPropertyValue(source, propertyName, value, Context.RootElement, node, Context, node); } else if (IsCollectionItem(node, parentNode) && parentNode is IElementNode) { // Collection element, implicit content, or implicit collection element. string contentProperty; if (typeof (IEnumerable).GetTypeInfo().IsAssignableFrom(Context.Types[parentElement].GetTypeInfo())) { var source = Values[parentNode]; if (!(typeof (ResourceDictionary).IsAssignableFrom(Context.Types[parentElement]))) { var addMethod = Context.Types[parentElement].GetRuntimeMethods().First(mi => mi.Name == "Add" && mi.GetParameters().Length == 1); addMethod.Invoke(source, new[] { value }); } } else if ((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; var source = Values[parentNode]; SetPropertyValue(source, name, value, Context.RootElement, node, Context, node); } } else if (IsCollectionItem(node, parentNode) && parentNode is ListNode) { var parentList = (ListNode)parentNode; var source = Values[parentNode.Parent]; if (Skips.Contains(parentList.XmlName)) return; var elementType = source.GetType(); var localname = parentList.XmlName.LocalName; GetRealNameAndType(ref elementType, parentList.XmlName.NamespaceURI, ref localname, Context, node); PropertyInfo propertyInfo = null; try { propertyInfo = elementType.GetRuntimeProperty(localname); } catch (AmbiguousMatchException) { // Get most derived instance of property foreach (var property in elementType.GetRuntimeProperties().Where(prop => prop.Name == localname)) { if (propertyInfo == null || propertyInfo.DeclaringType.IsAssignableFrom(property.DeclaringType)) propertyInfo = property; } } if (propertyInfo == null) throw new XamlParseException(string.Format("Property {0} not found", localname), node); MethodInfo getter; if (!propertyInfo.CanRead || (getter = propertyInfo.GetMethod) == null) throw new XamlParseException(string.Format("Property {0} does not have an accessible getter", localname), node); IEnumerable collection; if ((collection = getter.Invoke(source, new object[] { }) as IEnumerable) == null) throw new XamlParseException(string.Format("Property {0} is null or is not IEnumerable", localname), node); MethodInfo addMethod; if ( (addMethod = collection.GetType().GetRuntimeMethods().First(mi => mi.Name == "Add" && mi.GetParameters().Length == 1)) == null) throw new XamlParseException(string.Format("Value of {0} does not have a Add() method", localname), node); addMethod.Invoke(collection, new[] { Values[node] }); } }
public void Visit(ElementNode node, INode parentNode) { if (node.SkipPrefix((node.NamespaceResolver ?? parentNode.NamespaceResolver)?.LookupPrefix(node.NamespaceURI))) return; //if this node is an IMarkupExtension, invoke ProvideValue() and replace the variable var vardef = Context.Variables[node]; var vardefref = new VariableDefinitionReference(vardef); Context.IL.Append(ProvideValue(vardefref, Context, Module, node)); if (vardef != vardefref.VariableDefinition) { vardef = vardefref.VariableDefinition; Context.Body.Variables.Add(vardef); Context.Variables[node] = vardef; } XmlName propertyName; if (TryGetPropertyName(node, parentNode, out propertyName)) { if (skips.Contains(propertyName)) return; if (propertyName == XmlName._CreateContent) SetDataTemplate((IElementNode)parentNode, node, Context, node); else SetPropertyValue(Context.Variables[(IElementNode)parentNode], propertyName, node, Context, node); } else if (IsCollectionItem(node, parentNode) && parentNode is IElementNode) { // Collection element, implicit content, or implicit collection element. string contentProperty; var parentVar = Context.Variables[(IElementNode)parentNode]; if (parentVar.VariableType.ImplementsInterface(Module.Import(typeof (IEnumerable)))) { var elementType = parentVar.VariableType; if (elementType.FullName != "Xamarin.Forms.ResourceDictionary" && elementType.Resolve().BaseType.FullName != "Xamarin.Forms.ResourceDictionary") { var adderTuple = elementType.GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, Module).First(); var adderRef = Module.Import(adderTuple.Item1); adderRef = Module.Import(adderRef.ResolveGenericParameters(adderTuple.Item2, Module)); Context.IL.Emit(OpCodes.Ldloc, parentVar); Context.IL.Emit(OpCodes.Ldloc, vardef); Context.IL.Emit(OpCodes.Callvirt, adderRef); if (adderRef.ReturnType.FullName != "System.Void") Context.IL.Emit(OpCodes.Pop); } } else if ((contentProperty = GetContentProperty(parentVar.VariableType)) != null) { var name = new XmlName(node.NamespaceURI, contentProperty); if (skips.Contains(name)) return; SetPropertyValue(Context.Variables[(IElementNode)parentNode], name, node, Context, node); } } else if (IsCollectionItem(node, parentNode) && parentNode is ListNode) { // IL_000d: ldloc.2 // IL_000e: callvirt instance class [mscorlib]System.Collections.Generic.IList`1<!0> class [Xamarin.Forms.Core]Xamarin.Forms.Layout`1<class [Xamarin.Forms.Core]Xamarin.Forms.View>::get_Children() // IL_0013: ldloc.0 // IL_0014: callvirt instance void class [mscorlib]System.Collections.Generic.ICollection`1<class [Xamarin.Forms.Core]Xamarin.Forms.View>::Add(!0) var parentList = (ListNode)parentNode; var parent = Context.Variables[((IElementNode)parentNode.Parent)]; if (skips.Contains(parentList.XmlName)) return; var elementType = parent.VariableType; var localname = parentList.XmlName.LocalName; GetNameAndTypeRef(ref elementType, parentList.XmlName.NamespaceURI, ref localname, Context, node); TypeReference propertyDeclaringType; var property = elementType.GetProperty(pd => pd.Name == localname, out propertyDeclaringType); MethodDefinition propertyGetter; if (property != null && (propertyGetter = property.GetMethod) != null && propertyGetter.IsPublic) { var propertyGetterRef = Module.Import(propertyGetter); propertyGetterRef = Module.Import(propertyGetterRef.ResolveGenericParameters(propertyDeclaringType, Module)); var propertyType = propertyGetterRef.ReturnType.ResolveGenericParameters(propertyDeclaringType); var adderTuple = propertyType.GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, Module).First(); var adderRef = Module.Import(adderTuple.Item1); adderRef = Module.Import(adderRef.ResolveGenericParameters(adderTuple.Item2, Module)); Context.IL.Emit(OpCodes.Ldloc, parent); Context.IL.Emit(OpCodes.Callvirt, propertyGetterRef); Context.IL.Emit(OpCodes.Ldloc, vardef); Context.IL.Emit(OpCodes.Callvirt, adderRef); if (adderRef.ReturnType.FullName != "System.Void") Context.IL.Emit(OpCodes.Pop); } } }
public void Visit(ElementNode node, INode parentNode) { object value = null; if (node.SkipPrefix(node.NamespaceResolver.LookupPrefix(node.NamespaceURI))) return; XamlParseException xpe; var type = XamlParser.GetElementType(node.XmlType, node, Context.RootElement?.GetType().GetTypeInfo().Assembly, out xpe); if (xpe != null) throw xpe; Context.Types[node] = type; string ctorargname; if (IsXaml2009LanguagePrimitive(node)) value = CreateLanguagePrimitive(type, node); else if (node.Properties.ContainsKey(XmlName.xArguments) || node.Properties.ContainsKey(XmlName.xFactoryMethod)) value = CreateFromFactory(type, node); else if ( type.GetTypeInfo() .DeclaredConstructors.Any( ci => ci.IsPublic && ci.GetParameters().Length != 0 && ci.GetParameters().All(pi => pi.CustomAttributes.Any(attr => attr.AttributeType == typeof (ParameterAttribute)))) && ValidateCtorArguments(type, node, out ctorargname)) value = CreateFromParameterizedConstructor(type, node); else if (!type.GetTypeInfo().DeclaredConstructors.Any(ci => ci.IsPublic && ci.GetParameters().Length == 0) && !ValidateCtorArguments(type, node, out ctorargname)) { throw new XamlParseException( String.Format("The Property {0} is required to create a {1} object.", ctorargname, type.FullName), node); } else { //this is a trick as the DataTemplate parameterless ctor is internal, and we can't CreateInstance(..., false) on WP7 try { if (type == typeof (DataTemplate)) value = new DataTemplate(); if (type == typeof (ControlTemplate)) value = new ControlTemplate(); if (value == null && node.CollectionItems.Any() && node.CollectionItems.First() is ValueNode) { var serviceProvider = new XamlServiceProvider(node, Context); var converted = ((ValueNode)node.CollectionItems.First()).Value.ConvertTo(type, () => type.GetTypeInfo(), serviceProvider); if (converted != null && converted.GetType() == type) value = converted; } if (value == null) value = Activator.CreateInstance(type); } catch (TargetInvocationException e) { if (e.InnerException is XamlParseException || e.InnerException is XmlException) throw e.InnerException; throw; } } Values[node] = value; var typeExtension = value as TypeExtension; if (typeExtension != null) { var serviceProvider = new XamlServiceProvider(node, Context); var visitor = new ApplyPropertiesVisitor(Context); foreach (var cnode in node.Properties.Values.ToList()) cnode.Accept(visitor, node); foreach (var cnode in node.CollectionItems) cnode.Accept(visitor, node); value = typeExtension.ProvideValue(serviceProvider); node.Properties.Clear(); node.CollectionItems.Clear(); Values[node] = value; } if (value is BindableObject) NameScope.SetNameScope(value as BindableObject, node.Namescope); }
public void Visit(ElementNode node, INode parentNode) { if (node.SkipPrefix(node.NamespaceResolver.LookupPrefix(node.NamespaceURI))) { return; } var value = Values[node]; var parentElement = parentNode as IElementNode; var markupExtension = value as IMarkupExtension; var valueProvider = value as IValueProvider; //Set Resources in ResourcesDictionaries if (IsCollectionItem(node, parentNode) && parentNode is IElementNode) { if (typeof(IEnumerable).IsAssignableFrom(Context.Types[parentElement])) { var source = Values[parentNode]; if (typeof(ResourceDictionary).IsAssignableFrom(Context.Types[parentElement]) && value is Style && !node.Properties.ContainsKey(XmlName.xKey)) { node.Accept(new ApplyPropertiesVisitor(Context), parentNode); if (markupExtension != null) { var serviceProvider = new XamlServiceProvider(node, Context); value = markupExtension.ProvideValue(serviceProvider); } if (valueProvider != null) { var serviceProvider = new XamlServiceProvider(node, Context); value = valueProvider.ProvideValue(serviceProvider); } ((ResourceDictionary)source).Add(value as Style); } else if (typeof(ResourceDictionary).IsAssignableFrom(Context.Types[parentElement]) && !node.Properties.ContainsKey(XmlName.xKey)) { throw new XamlParseException("resources in ResourceDictionary require a x:Key attribute", node); } else if (typeof(ResourceDictionary).IsAssignableFrom(Context.Types[parentElement]) && node.Properties.ContainsKey(XmlName.xKey)) { node.Accept(new ApplyPropertiesVisitor(Context), parentNode); if (markupExtension != null) { var serviceProvider = new XamlServiceProvider(node, Context); value = markupExtension.ProvideValue(serviceProvider); } if (valueProvider != null) { var serviceProvider = new XamlServiceProvider(node, Context); value = valueProvider.ProvideValue(serviceProvider); } ((ResourceDictionary)source).Add((string)(((ValueNode)node.Properties[XmlName.xKey]).Value), value); } } } //Set RD to VE XmlName propertyName; if (ApplyPropertiesVisitor.TryGetPropertyName(node, parentNode, out propertyName)) { if ((propertyName.LocalName == "Resources" || propertyName.LocalName.EndsWith(".Resources", StringComparison.Ordinal)) && value is ResourceDictionary) { var source = Values[parentNode]; ApplyPropertiesVisitor.SetPropertyValue(source, propertyName, value, Context.RootElement, node, Context, node); } } }
public void Visit(ElementNode node, INode parentNode) { if (node.SkipPrefix(node.NamespaceResolver.LookupPrefix(node.NamespaceURI))) { return; } var value = Values[node]; var parentElement = parentNode as IElementNode; var markupExtension = value as IMarkupExtension; var valueProvider = value as IValueProvider; if (markupExtension != null) { var serviceProvider = new XamlServiceProvider(node, Context); value = markupExtension.ProvideValue(serviceProvider); } if (valueProvider != null) { var serviceProvider = new XamlServiceProvider(node, Context); value = valueProvider.ProvideValue(serviceProvider); } XmlName propertyName; if (TryGetPropertyName(node, parentNode, out propertyName)) { if (Skips.Contains(propertyName)) { return; } if (parentElement.SkipProperties.Contains(propertyName)) { return; } var source = Values[parentNode]; if (propertyName == XmlName._CreateContent && source is ElementTemplate) { SetTemplate(source as ElementTemplate, node); } else { SetPropertyValue(source, propertyName, value, Context.RootElement, node, Context, node); } } else if (IsCollectionItem(node, parentNode) && parentNode is IElementNode) { // Collection element, implicit content, or implicit collection element. string contentProperty; if (typeof(IEnumerable).GetTypeInfo().IsAssignableFrom(Context.Types[parentElement].GetTypeInfo())) { var source = Values[parentNode]; if (!(typeof(ResourceDictionary).IsAssignableFrom(Context.Types[parentElement]))) { var addMethod = Context.Types[parentElement].GetRuntimeMethods().First(mi => mi.Name == "Add" && mi.GetParameters().Length == 1); addMethod.Invoke(source, new[] { value }); } } else if ((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; } var source = Values[parentNode]; SetPropertyValue(source, name, value, Context.RootElement, node, Context, node); } } else if (IsCollectionItem(node, parentNode) && parentNode is ListNode) { var parentList = (ListNode)parentNode; var source = Values[parentNode.Parent]; if (Skips.Contains(parentList.XmlName)) { return; } var elementType = source.GetType(); var localname = parentList.XmlName.LocalName; GetRealNameAndType(ref elementType, parentList.XmlName.NamespaceURI, ref localname, Context, node); PropertyInfo propertyInfo = null; try { propertyInfo = elementType.GetRuntimeProperty(localname); } catch (AmbiguousMatchException) { // Get most derived instance of property foreach (var property in elementType.GetRuntimeProperties().Where(prop => prop.Name == localname)) { if (propertyInfo == null || propertyInfo.DeclaringType.IsAssignableFrom(property.DeclaringType)) { propertyInfo = property; } } } if (propertyInfo == null) { throw new XamlParseException(string.Format("Property {0} not found", localname), node); } MethodInfo getter; if (!propertyInfo.CanRead || (getter = propertyInfo.GetMethod) == null) { throw new XamlParseException(string.Format("Property {0} does not have an accessible getter", localname), node); } IEnumerable collection; if ((collection = getter.Invoke(source, new object[] { }) as IEnumerable) == null) { throw new XamlParseException(string.Format("Property {0} is null or is not IEnumerable", localname), node); } MethodInfo addMethod; if ( (addMethod = collection.GetType().GetRuntimeMethods().First(mi => mi.Name == "Add" && mi.GetParameters().Length == 1)) == null) { throw new XamlParseException(string.Format("Value of {0} does not have a Add() method", localname), node); } addMethod.Invoke(collection, new[] { Values[node] }); } }
public void Visit(ElementNode node, INode parentNode) { object value = null; if (node.SkipPrefix(node.NamespaceResolver.LookupPrefix(node.NamespaceURI))) { return; } XamlParseException xpe; var type = XamlParser.GetElementType(node.XmlType, node, Context.RootElement?.GetType().GetTypeInfo().Assembly, out xpe); if (xpe != null) { throw xpe; } Context.Types[node] = type; string ctorargname; if (IsXaml2009LanguagePrimitive(node)) { value = CreateLanguagePrimitive(type, node); } else if (node.Properties.ContainsKey(XmlName.xArguments) || node.Properties.ContainsKey(XmlName.xFactoryMethod)) { value = CreateFromFactory(type, node); } else if ( type.GetTypeInfo() .DeclaredConstructors.Any( ci => ci.IsPublic && ci.GetParameters().Length != 0 && ci.GetParameters().All(pi => pi.CustomAttributes.Any(attr => attr.AttributeType == typeof(ParameterAttribute)))) && ValidateCtorArguments(type, node, out ctorargname)) { value = CreateFromParameterizedConstructor(type, node); } else if (!type.GetTypeInfo().DeclaredConstructors.Any(ci => ci.IsPublic && ci.GetParameters().Length == 0) && !ValidateCtorArguments(type, node, out ctorargname)) { throw new XamlParseException( String.Format("The Property {0} is required to create a {1} object.", ctorargname, type.FullName), node); } else { //this is a trick as the DataTemplate parameterless ctor is internal, and we can't CreateInstance(..., false) on WP7 try { if (type == typeof(DataTemplate)) { value = new DataTemplate(); } if (type == typeof(ControlTemplate)) { value = new ControlTemplate(); } if (value == null && node.CollectionItems.Any() && node.CollectionItems.First() is ValueNode) { var serviceProvider = new XamlServiceProvider(node, Context); var converted = ((ValueNode)node.CollectionItems.First()).Value.ConvertTo(type, () => type.GetTypeInfo(), serviceProvider); if (converted != null && converted.GetType() == type) { value = converted; } } if (value == null) { value = Activator.CreateInstance(type); } } catch (TargetInvocationException e) { if (e.InnerException is XamlParseException || e.InnerException is XmlException) { throw e.InnerException; } throw; } } Values[node] = value; var typeExtension = value as TypeExtension; if (typeExtension != null) { var serviceProvider = new XamlServiceProvider(node, Context); var visitor = new ApplyPropertiesVisitor(Context); foreach (var cnode in node.Properties.Values.ToList()) { cnode.Accept(visitor, node); } foreach (var cnode in node.CollectionItems) { cnode.Accept(visitor, node); } value = typeExtension.ProvideValue(serviceProvider); node.Properties.Clear(); node.CollectionItems.Clear(); Values[node] = value; } if (value is BindableObject) { NameScope.SetNameScope(value as BindableObject, node.Namescope); } }