James
James

Reputation: 143

Serializing Object whose type is not known at compile time

I got a list of models which may vary and their type cannot be known at compile time. The only options I have to implement this collection is either by making a List<Object> or List<dynamic> (I know the first one is faster and better). The problem is that when trying to serialize this collection, the .Net's XmlSerializer throws an exception saying that "Data whose type is not known at compile time cannot be serialized". The question is, according to this exception, is it possible at all to do this and if yes how can this be done efficiently.

Update:

Binary serialization is not an option here (can't use it)

Upvotes: 1

Views: 324

Answers (2)

MatteoSp
MatteoSp

Reputation: 3048

Serialize the list item after item, like:

public class ModelA
{
    public int Foo { get; set; }
}

public class ModelB
{
    public string Bar { get; set; }
}


class Program
{
    static void Main(string[] args)
    {
        var stream = new MemoryStream();
        var writer = XmlWriter.Create(stream);
        var list = new List<object>() 
        {
            new ModelA() { Foo = 9 },
            new ModelB() { Bar = "some string" }
        };

        writer.WriteStartElement("root");
        list.ForEach(x => ToXml(x, writer));
        writer.WriteEndElement();

        writer.Flush();
        stream.Seek(0, SeekOrigin.Begin);

        var doc = new XmlDocument();
        doc.Load(XmlReader.Create(stream));
        Console.WriteLine(doc.OuterXml);

        Console.ReadLine();
    }

    private static void ToXml(object obj, XmlWriter writer)
    {
        var serializer = new XmlSerializer(obj.GetType());

        serializer.Serialize(writer, obj);
    }
}

Upvotes: 0

phoog
phoog

Reputation: 43076

(Note: the earlier comments below refer to a different solution from an earlier version of the question.)

Have you tried this?

var types = theList.Select(o => o.GetType()).Distinct().ToArray();
var serializer = new XmlSerializer(typeof(List<object>), types);
...

Deserialization will be harder, of course; you'll need to parse the necessary types out of the XML and then use reflection to get the type objects into an array so you can instantiate the XmlSerializer. You could simplify that somewhat by packaging the XML with some metadata that lists the necessary types.

Upvotes: 2

Related Questions