private void AddChild(Element parent) { Element child = this.CreateElement(); bool isOrphan; if (child is UnknownElement) { var browser = TypeBrowser.Create(parent.GetType()); TypeBrowser.ElementInfo elementInfo = browser.FindElement(this.GetXmlComponent()); if (elementInfo != null) { // We're not going to add it to the parent, which has the potential to // lose any attributes/child elements assigned to the unknown, but this // is the behaviour of the C++ version. this.PopulateElement(child); AssignValue(parent, elementInfo, child.InnerText); return; } isOrphan = true; } else { isOrphan = !this.AddChildToParent(parent, child); } this.PopulateElement(child); this.OnElementAdded(child); if (isOrphan) { parent.AddOrphan(child); // Save for later serialization } }
private void WriteElement( XmlWriter writer, XmlNamespaceManager manager, Element element, TypeBrowser.ElementInfo elementInfo) { object value = elementInfo.GetValue(element); // Make sure it needs saving if (value != null) { if (value is IEnumerable <Element> collection) { foreach (Element child in collection) { this.SerializeElement(writer, manager, child); } } else if (string.IsNullOrEmpty(elementInfo.Component.Name)) { // If the component is null then it's a normal element this.SerializeElement(writer, manager, (Element)value); } else { writer.WriteStartElement(elementInfo.Component.Name, elementInfo.Component.Namespace); WriteData(writer, this.GetString(value)); writer.WriteEndElement(); } } }
private static IEnumerable <Element> GetPropertyElements(Element element, TypeBrowser.ElementInfo info) { // All properties with their ElementName set to null will be Elements // Check here to avoid the GetValue the property is not an Element. if (string.IsNullOrEmpty(info.Component.Name)) { object value = info.GetValue(element); if (value is IEnumerable <Element> collection) { foreach (Element e in collection) { yield return(e); } } else if (value is Element propertyElement) { yield return(propertyElement); } } }
private static void AssignValue(object instance, TypeBrowser.ElementInfo elementInfo, string text) { // Get the type, checking if it's nullable, as TryParse doesn't exist on "int?" Type type = elementInfo.ValueType; Type nullableType = Nullable.GetUnderlyingType(type); if (nullableType != null) { type = nullableType; } if (ValueConverter.TryGetValue(type, text, out object value)) { if (value != null) { elementInfo.SetValue(instance, value); } else if ((nullableType != null) || !type.GetTypeInfo().IsValueType) { elementInfo.SetValue(instance, null); } } }
private void ProcessAttributes(Element element) { var browser = TypeBrowser.Create(element.GetType()); while (this.reader.MoveToNextAttribute()) { // Check for namespaces first if (string.Equals("xmlns", this.reader.Name, StringComparison.Ordinal)) { // Set default namespace only on unknown elements if (element is UnknownElement) { element.AddNamespace(string.Empty, this.reader.Value); } } else if (string.Equals("xmlns", this.reader.Prefix, StringComparison.Ordinal)) { element.AddNamespace(this.reader.LocalName, this.reader.Value); } else { // Just a normal attribute TypeBrowser.ElementInfo property = browser.FindAttribute( new XmlComponent(null, this.reader.LocalName, null)); // Attributes never have namespace info if (property != null) { AssignValue(element, property, this.reader.Value); } else { // Unknown, save for later serialization element.AddAttribute(new XmlComponent(this.reader)); } } } }