Serialize object to XML WITHIN a parent element

前端 未结 1 465
心在旅途
心在旅途 2021-01-24 01:35

I\'ve got a WPF C# program and at one point I need to serialize objects to XML. In other places, I\'ve been using this:

TextWriter writer = new StreamWriter(xmlF         


        
相关标签:
1条回答
  • 2021-01-24 01:59

    You are trying to serialize directly to some nested XElement inside an XDocument using XmlSerializer. Unfortunately, it seems that, when serializing directly to a LINQ-to-XML XElement using XmlSerializer together with XContainer.CreateWriter(), it is actually necessary to serialize to an empty XDocument thereby creating its root element. (I am not sure why this restriction exists, but it does.) Since this doesn't meet your needs, it is easy to serialize to a temporary XDocument, remove its root node, then add that node to your overall element hierarchy.

    Also, when adding an object to your database using an objectName that already has XML data stored, you need to remove the old data.

    I refactored your code into extension methods to accomplish this:

    public static class XmlExtensions
    {
        public static T Deserialize<T>(this XContainer element, XmlSerializer serializer = null)
        {
            using (var reader = element.CreateReader())
            {
                object result = (serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader);
                if (result is T)
                    return (T)result;
            }
            return default(T);
        }
    
        public static XElement SerializeToXElement<T>(this T obj, XmlSerializer serializer = null)
        {
            var doc = new XDocument();
            using (var writer = doc.CreateWriter())
                (serializer ?? new XmlSerializer(obj.GetType())).Serialize(writer, obj);
            var element = doc.Root;
            if (element != null)
                element.Remove();
            return element;
        }
    
        public static XName ContainerElementName { get { return (XName)"Object"; } }
    
        public static XName ContainerAttributeName { get { return (XName)"Name"; } }
    
        public static XElement SetItem<T>(this XDocument doc, string attributeValue, T obj)
        {
            return doc.SetItem(ContainerElementName, ContainerAttributeName, attributeValue, obj);
        }
    
        static XElement SetItem<T>(this XDocument doc, XName containerElementName, XName containerAttributeName, string attributeValue, T obj)
        {
            if (doc == null || containerElementName == null || containerAttributeName == null || attributeValue == null)
                throw new ArgumentNullException();
            if (doc.Root == null)
                throw new ArgumentException("doc.Root == null");
            var container = doc.Root.Elements(containerElementName).Where(e => (string)e.Attribute(containerAttributeName) == attributeValue).SingleOrDefault();
            if (container == null)
            {
                container = new XElement(containerElementName, new XAttribute(containerAttributeName, attributeValue));
                doc.Root.Add(container);
            }
            else
            {
                // Remove old content.
                container.RemoveNodes();
            }
    
            var element = obj.SerializeToXElement();
            container.Add(element);
            return element;
        }
    
        public static T GetItem<T>(this XDocument doc, string attributeValue)
        {
            return doc.GetItem<T>(ContainerElementName, ContainerAttributeName, attributeValue);
        }
    
        static T GetItem<T>(this XDocument doc, XName containerElementName, XName containerAttributeName, string attributeValue)
        {
            if (doc == null || containerElementName == null || containerAttributeName == null || attributeValue == null)
                throw new ArgumentNullException();
            if (doc.Root == null)
                throw new ArgumentException("doc.Root == null");
            var container = doc.Root.Elements(containerElementName).Where(e => (string)e.Attribute(containerAttributeName) == attributeValue).SingleOrDefault();
            if (container == null)
                return default(T);
            var element = container.Elements().SingleOrDefault();
            if (element == null)
                return default(T);
            return element.Deserialize<T>();
        }
    
        public static XDocument CreateDefaultXDocument()
        {
            var xml = @"<StoredObjects></StoredObjects>";
            return XDocument.Parse(xml);
        }
    }
    

    Now you can do

    doc.AddItem(MYOBJECT, objectName);
    

    And later

    var MYOBJECT2 = doc.GetItem<MYOBJECT_TYPE>(objectName);
    

    Example fiddle.

    0 讨论(0)
提交回复
热议问题