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); }
public object CreateFromFactory(Type nodeType, IElementNode node) { object[] arguments = CreateArgumentsArray(node); if (!node.Properties.ContainsKey(XmlName.xFactoryMethod)) { //non-default ctor object ret = Activator.CreateInstance(nodeType, BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance | BindingFlags.OptionalParamBinding, null, arguments, CultureInfo.CurrentCulture); if (ret is Element element) { if (null != Application.Current) { Application.Current.XamlResourceChanged += element.OnResourcesChanged; } element.IsCreateByXaml = true; } return(ret); } var factoryMethod = ((string)((ValueNode)node.Properties[XmlName.xFactoryMethod]).Value); Type[] types = arguments == null?System.Array.Empty <Type>() : arguments.Select(a => a.GetType()).ToArray(); Func <MethodInfo, bool> isMatch = m => { if (m.Name != factoryMethod) { return(false); } var p = m.GetParameters(); if (p.Length != types.Length) { return(false); } if (!m.IsStatic) { return(false); } for (var i = 0; i < p.Length; i++) { if ((p[i].ParameterType.IsAssignableFrom(types[i]))) { continue; } var op_impl = p[i].ParameterType.GetImplicitConversionOperator(fromType: types[i], toType: p[i].ParameterType) ?? types[i].GetImplicitConversionOperator(fromType: types[i], toType: p[i].ParameterType); if (op_impl == null) { return(false); } arguments[i] = op_impl.Invoke(null, new[] { arguments[i] }); } return(true); }; var mi = nodeType.GetRuntimeMethods().FirstOrDefault(isMatch); if (mi == null) { if (node is ElementNode elementNode) { var nodeTypeExtension = XamlParser.GetElementTypeExtension(node.XmlType, elementNode, Context.RootElement?.GetType().GetTypeInfo().Assembly); mi = nodeTypeExtension?.GetRuntimeMethods().FirstOrDefault(isMatch); } } if (mi == null) { throw new MissingMemberException($"No static method found for {nodeType.FullName}::{factoryMethod} ({string.Join(", ", types.Select(t => t.FullName))})"); } return(mi.Invoke(null, arguments)); }
public void Visit(ElementNode node, INode parentNode) { object value = null; 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($"The Property {ctorargname} is required to create a {type?.FullName} object.", 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); if (value is Element) { if (null != Application.Current) { Application.AddResourceChangedCallback(value, (value as Element).OnResourcesChanged); } if (value is BindableObject) { ((BindableObject)value).IsCreateByXaml = true; } } } } catch (TargetInvocationException e) { if (e.InnerException is XamlParseException || e.InnerException is XmlException) { throw e.InnerException; } throw; } } Values[node] = value; var markup = value as IMarkupExtension; if (markup != null && (value is TypeExtension || value is StaticExtension || value is ArrayExtension)) { 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 = markup.ProvideValue(serviceProvider); INode xKey; if (!node.Properties.TryGetValue(XmlName.xKey, out xKey)) { xKey = null; } node.Properties.Clear(); node.CollectionItems.Clear(); if (xKey != null) { node.Properties.Add(XmlName.xKey, xKey); } Values[node] = value; } if (value is BindableObject) { NameScope.SetNameScope(value as BindableObject, node.Namescope); } }
public void Visit(ElementNode node, INode parentNode) { object value = null; XamlParseException xpe; var type = XamlParser.GetElementType(node.XmlType, node, Context.RootElement?.GetType().GetTypeInfo().Assembly, out xpe); if (type == null) { throw new ArgumentNullException(null, "type should not be null"); } 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($"The Property {ctorargname} is required to create a {type?.FullName} object.", 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) { if (type.GetTypeInfo().DeclaredConstructors.Any(ci => ci.IsPublic && ci.GetParameters().Length == 0)) { //default constructor value = Activator.CreateInstance(type); } else { ConstructorInfo constructorInfo = null; //constructor with all default parameters foreach (var constructor in type.GetConstructors()) { if (!constructor.IsStatic) { bool areAllParamsDefault = true; foreach (var param in constructor.GetParameters()) { if (!param.HasDefaultValue) { areAllParamsDefault = false; break; } } if (areAllParamsDefault) { if (null == constructorInfo) { constructorInfo = constructor; } else { throw new XamlParseException($"{type.FullName} has more than one constructor which params are all default.", node); } } } } if (null == constructorInfo) { throw new XamlParseException($"{type.FullName} has no constructor which params are all default.", node); } List <object> defaultParams = new List <object>(); foreach (var param in constructorInfo.GetParameters()) { defaultParams.Add(param.DefaultValue); } value = Activator.CreateInstance(type, defaultParams.ToArray()); } if (value is Element element) { element.IsCreateByXaml = true; element.LineNumber = node.LineNumber; element.LinePosition = node.LinePosition; } } } catch (TargetInvocationException e) { if (e.InnerException is XamlParseException || e.InnerException is XmlException) { throw e.InnerException; } throw; } } Values[node] = value; var markup = value as IMarkupExtension; if (markup != null && (value is TypeExtension || value is StaticExtension || value is ArrayExtension)) { 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 = markup.ProvideValue(serviceProvider); INode xKey; if (!node.Properties.TryGetValue(XmlName.xKey, out xKey)) { xKey = null; } node.Properties.Clear(); node.CollectionItems.Clear(); if (xKey != null) { node.Properties.Add(XmlName.xKey, xKey); } Values[node] = value; } if (value is BindableObject) { NameScope.SetNameScope(value as BindableObject, node.Namescope); } }