6

I have a object {System.Collections.Generic.List<object>} that contains 1000 object {DynamicData} inside of it, each one with 4 keys and values and one more List with 2 keys and values inside. I need to serialize this object into a XML File, i tried normal serialization but it gives me this exception = The type DynamicData was not expected, how can i serialize this object?

Here is the code:

           //output is the name of my object
            XmlSerializer xsSubmit = new XmlSerializer(output.GetType());
            var xml = "";

            using (var sww = new StringWriter())
            {
                using (XmlWriter writers = XmlWriter.Create(sww))
                {
                    try
                    {
                        xsSubmit.Serialize(writers, output);
                    }
                    catch (Exception ex)
                    {

                        throw;
                    }
                    xml = sww.ToString(); // Your XML
                }
            }

I can create the xml file writing line by line and element by element, but i want something more faster and with less code. The structure of my object is like this:

output (count 1000)
 [0]
   Costumer - "Costumername"
   DT - "Date"
   Key - "Key"
   Payment - "x"
   [0]
    Adress - "x"
    Number - "1"
 [1]...
 [2]...
Lucio Zenir
  • 365
  • 2
  • 8
  • 18
  • Off-topic: you are actually dealing with _costumers_? I mean, there _must_ be _some_ systems in which they exist, I just never ran came across one. – oerkelens Dec 11 '17 at 17:11
  • This is just a example of object, now it's costumers, but it can be anything you know? I will always have this object with differente kind of data inside, sometimes it will not have a list inside, sometimes it will have more than 1 child-list. PS: i get this object from a DB select, or from a file reader..... – Lucio Zenir Dec 11 '17 at 17:16
  • It's not clear what is the type you're serializing. Does it have `[Serializable]` attribute? Why `object` and not the concrete type? – JohnyL Dec 11 '17 at 17:23
  • It does not have `[Serializable]` attribute Needs to be a `object`, i get this `object` from another part of the system, the `object` structure is in the post, every `field` of the `object` is a `dynamic data`. So the `object` is a `List` that contains `dynamic objects`, inside those may contain another `Lists` – Lucio Zenir Dec 11 '17 at 17:26
  • 1
    `XmlSerializer` isn't really well suited to what you want to do. Firstly, thinking of your dynamic objects as dictionaries, `XmlSerializer` doesn't support dictionaries directly. See [Why doesn't XmlSerializer support Dictionary?](https://stackoverflow.com/q/2911514) and [How to XML-serialize a dictionary](https://stackoverflow.com/q/3671259). – dbc Dec 11 '17 at 17:46
  • 1
    Secondly, when serializing polymorphic members, `XmlSerializer` will only serialize known, whitelisted types -- for instance, those included with [`[XmlInclude]`](https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlincludeattribute(v=vs.110).aspx) as shown in [xsi:type attribute messing up C# XML deserialization](https://stackoverflow.com/a/36365689/3744182). This is for security reasons, it prevents construction of risky types such as those described in [TypeNameHandling caution in Newtonsoft Json](https://stackoverflow.com/q/39565954). – dbc Dec 11 '17 at 18:01
  • 1
    For possible workarounds, see [XML Serialization and Inherited Types](https://stackoverflow.com/q/20084) or [Serializing an array of multiple types using XmlSerializer](https://stackoverflow.com/q/28462449/3744182) - but you will need to be careful of possible security hazards. – dbc Dec 11 '17 at 18:01

1 Answers1

5

You can implement your own serialize object by using IXmlSerializable

[Serializable]
public class ObjectSerialize :  IXmlSerializable
{
    public List<object> ObjectList { get; set; }

    public XmlSchema GetSchema()
    {
        return new XmlSchema();
    }

    public void ReadXml(XmlReader reader)
    {

    }

    public void WriteXml(XmlWriter writer)
    {
        foreach (var obj in ObjectList)
        {   
            //Provide elements for object item
            writer.WriteStartElement("Object");
            var properties = obj.GetType().GetProperties();
            foreach (var propertyInfo in properties)
            {   
                //Provide elements for per property
                writer.WriteElementString(propertyInfo.Name, propertyInfo.GetValue(obj).ToString());
            }
            writer.WriteEndElement();
        }
    }
}

Usage;

        var output = new List<object>
        {
            new { Sample = "Sample" }
        };
        var objectSerialize = new ObjectSerialize
        {
            ObjectList = output
        };
        XmlSerializer xsSubmit = new XmlSerializer(typeof(ObjectSerialize));
        var xml = "";

        using (var sww = new StringWriter())
        {
            using (XmlWriter writers = XmlWriter.Create(sww))
            {
                try
                {
                    xsSubmit.Serialize(writers, objectSerialize);
                }
                catch (Exception ex)
                {

                    throw;
                }
                xml = sww.ToString(); // Your XML
            }
        }

Output

<?xml version="1.0" encoding="utf-16"?>
<ObjectSerialize>
    <Object>
        <Sample>Sample</Sample>
    </Object>
</ObjectSerialize>

Note : Be careful with that, if you want to deserialize with same type (ObjectSerialize) you should provide ReadXml. And if you want to specify schema, you should provide GetSchema too.

lucky
  • 12,734
  • 4
  • 24
  • 46
  • I can't create de object in my code, i will get him from memory. How do i implement your code with the object already created? like this: `object output = (The part of the memory that it is stored);` – Lucio Zenir Dec 11 '17 at 18:57
  • I declared "Sample" object for making an example. Ignore it, and set your output object in ObjectSerialize instance. – lucky Dec 11 '17 at 19:10
  • Ok, and how can i create the XML File after the serialize? – Lucio Zenir Dec 11 '17 at 19:25
  • Just use System.IO.File.WriteAllText(@"C:\objectXml.xml",xml); – lucky Dec 11 '17 at 19:29
  • It works, i will test in other objects, thanks a lot – Lucio Zenir Dec 11 '17 at 19:36
  • It does not work for the secondary level of lists, this is the xml that the code created: ` 99503 1999-10-20 Please leave packages in shed by driveway.
    System.Collections.Generic.List1[Address]
    Item
    `
    – Lucio Zenir Dec 11 '17 at 19:39
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/160958/discussion-between-rainman-and-lucio-zenir). – lucky Dec 11 '17 at 19:43
  • Thank you for your example @lucky! In reference to @lucio-zenir, for anyone looking to be able to pass in anonymous objects that have nested anonymous objects, here is an example that I created: https://dotnetfiddle.net/WuuOWg – csteele Dec 03 '21 at 19:40