internal static void ParseObjectAttribute(XamlObject obj, XmlAttribute attribute, bool real) { XamlPropertyInfo propertyInfo = GetPropertyInfo(obj.Instance, obj.ElementType, attribute, obj.OwnerDocument.TypeFinder); XamlPropertyValue value = null; var valueText = attribute.Value; if (valueText.StartsWith("{", StringComparison.Ordinal) && !valueText.StartsWith("{}", StringComparison.Ordinal)) { var xamlObject = MarkupExtensionParser.Parse(valueText, obj, real ? attribute : null); value = xamlObject; } else { if (real) { value = new XamlTextValue(obj.OwnerDocument, attribute); } else { value = new XamlTextValue(obj.OwnerDocument, valueText); } } var property = new XamlProperty(obj, propertyInfo, value); obj.AddProperty(property); }
void ParseObjectContent(XamlObject obj, XmlElement element, XamlPropertyInfo defaultProperty, XamlTextValue initializeFromTextValueInsteadOfConstructor) { bool isDefaultValueSet = false; XamlProperty collectionProperty = null; object collectionInstance = null; Type collectionType = null; XmlElement collectionPropertyElement = null; var elementChildNodes = GetNormalizedChildNodes(element); if (defaultProperty == null && obj.Instance != null && CollectionSupport.IsCollectionType(obj.Instance.GetType())) { XamlObject parentObj = obj.ParentObject; var parentElement = element.ParentNode; XamlPropertyInfo propertyInfo; if (parentObj != null) { propertyInfo = GetPropertyInfo(settings.TypeFinder, parentObj.Instance, parentObj.ElementType, parentElement.NamespaceURI, parentElement.LocalName); collectionProperty = FindExistingXamlProperty(parentObj, propertyInfo); } collectionInstance = obj.Instance; collectionType = obj.ElementType; collectionPropertyElement = element; } else if (defaultProperty != null && defaultProperty.IsCollection && !element.IsEmpty) { foreach (XmlNode childNode in elementChildNodes) { currentParsedNode = childNode; XmlElement childElement = childNode as XmlElement; if (childElement == null || !ObjectChildElementIsPropertyElement(childElement)) { obj.AddProperty(collectionProperty = new XamlProperty(obj, defaultProperty)); collectionType = defaultProperty.ReturnType; collectionInstance = defaultProperty.GetValue(obj.Instance); break; } } } currentParsedNode = element; if (collectionType != null && collectionInstance == null && elementChildNodes.Count() == 1) { var firstChild = elementChildNodes.First() as XmlElement; if (ObjectChildElementIsCollectionInstance(firstChild, collectionType)) { collectionInstance = ParseObject(firstChild); collectionProperty.PropertyValue = (XamlPropertyValue)collectionInstance; } else { throw new XamlLoadException("Collection Instance is null"); } } else { foreach (XmlNode childNode in elementChildNodes) { currentParsedNode = childNode; XmlElement childElement = childNode as XmlElement; if (childElement != null) { if (childElement.NamespaceURI == XamlConstants.XamlNamespace) { continue; } if (ObjectChildElementIsPropertyElement(childElement)) { ParseObjectChildElementAsPropertyElement(obj, childElement, defaultProperty); continue; } } if (initializeFromTextValueInsteadOfConstructor != null) { continue; } XamlPropertyValue childValue = ParseValue(childNode); if (childValue != null) { if (collectionProperty != null) { collectionProperty.ParserAddCollectionElement(collectionPropertyElement, childValue); CollectionSupport.AddToCollection(collectionType, collectionInstance, childValue); } else if (collectionProperty == null && collectionInstance is ResourceDictionary) { CollectionSupport.AddToCollection(collectionType, collectionInstance, childValue); } else { if (defaultProperty == null) { throw new XamlLoadException( "This element does not have a default value, cannot assign to it"); } if (isDefaultValueSet) { throw new XamlLoadException("default property may have only one value assigned"); } obj.AddProperty(new XamlProperty(obj, defaultProperty, childValue)); isDefaultValueSet = true; } } } } currentParsedNode = element; }
XamlObject ParseObject(XmlElement element) { Type elementType = settings.TypeFinder.GetType(element.NamespaceURI, element.LocalName); if (typeof(FrameworkTemplate).IsAssignableFrom(elementType)) { var xamlObj = new XamlObject(document, element, elementType, TemplateHelper.GetFrameworkTemplate(element, currentXamlObject)); xamlObj.ParentObject = currentXamlObject; return(xamlObj); } if (elementType == null) { elementType = settings.TypeFinder.GetType(element.NamespaceURI, element.LocalName + "Extension"); if (elementType == null) { throw new XamlLoadException("Cannot find type " + element.Name); } } XmlSpace oldXmlSpace = currentXmlSpace; XamlObject parentXamlObject = currentXamlObject; if (element.HasAttribute("xml:space")) { currentXmlSpace = (XmlSpace)Enum.Parse(typeof(XmlSpace), element.GetAttribute("xml:space"), true); } XamlPropertyInfo defaultProperty = GetDefaultProperty(elementType); XamlTextValue initializeFromTextValueInsteadOfConstructor = null; if (defaultProperty == null) { int numberOfTextNodes = 0; bool onlyTextNodes = true; foreach (XmlNode childNode in element.ChildNodes) { if (childNode.NodeType == XmlNodeType.Text) { numberOfTextNodes++; } else if (childNode.NodeType == XmlNodeType.Element) { onlyTextNodes = false; } } if (elementType == typeof(string) && numberOfTextNodes == 0) { initializeFromTextValueInsteadOfConstructor = new XamlTextValue(document, string.Empty); } else if (onlyTextNodes && numberOfTextNodes == 1) { foreach (XmlNode childNode in element.ChildNodes) { if (childNode.NodeType == XmlNodeType.Text) { currentParsedNode = childNode; initializeFromTextValueInsteadOfConstructor = (XamlTextValue)ParseValue(childNode); } } } } currentParsedNode = element; object instance; if (initializeFromTextValueInsteadOfConstructor != null) { instance = TypeDescriptor.GetConverter(elementType) .ConvertFromString( document.GetTypeDescriptorContext(null), CultureInfo.InvariantCulture, initializeFromTextValueInsteadOfConstructor.Text); } else { instance = settings.CreateInstanceCallback(elementType, emptyObjectArray); } XamlObject obj = new XamlObject(document, element, elementType, instance); currentXamlObject = obj; obj.ParentObject = parentXamlObject; if (parentXamlObject == null && obj.Instance is DependencyObject) { NameScope.SetNameScope((DependencyObject)obj.Instance, new NameScope()); } ISupportInitialize iSupportInitializeInstance = instance as ISupportInitialize; if (iSupportInitializeInstance != null) { iSupportInitializeInstance.BeginInit(); } foreach (XmlAttribute attribute in element.Attributes) { if (attribute.Value.StartsWith("clr-namespace", StringComparison.OrdinalIgnoreCase)) { // the format is "clr-namespace:<Namespace here>;assembly=<Assembly name here>" var clrNamespace = attribute.Value.Split(new[] { ':', ';', '=' }); if (clrNamespace.Length == 4) { // get the assembly name var assembly = settings.TypeFinder.LoadAssembly(clrNamespace[3]); if (assembly != null) { settings.TypeFinder.RegisterAssembly(assembly); } } else { // if no assembly name is there, then load the assembly of the opened file. var assembly = settings.TypeFinder.LoadAssembly(null); if (assembly != null) { settings.TypeFinder.RegisterAssembly(assembly); } } } if (attribute.NamespaceURI == XamlConstants.XmlnsNamespace) { continue; } if (attribute.Name == "xml:space") { continue; } if (GetAttributeNamespace(attribute) == XamlConstants.XamlNamespace || GetAttributeNamespace(attribute) == XamlConstants.Xaml2009Namespace) { if (attribute.LocalName == "Name") { try { NameScopeHelper.NameChanged(obj, null, attribute.Value); } catch (Exception x) { ReportException(x, attribute); } } continue; } ParseObjectAttribute(obj, attribute); } ParseObjectContent(obj, element, defaultProperty, initializeFromTextValueInsteadOfConstructor); if (iSupportInitializeInstance != null) { iSupportInitializeInstance.EndInit(); } currentXmlSpace = oldXmlSpace; currentXamlObject = parentXamlObject; return(obj); }