I cannot serialize a list of objects in C # using XmlSerializer

I have a list of many tests implementing the IDoTest interface that I want to save to a file. I also want to read from this file.

It seemed natural to just use the XmlSerializer to store objects in my IDoTest list. But when I do this, I get a vague regret that I cannot make this mistake in the vicinity of System.Xml.Serialization.TypeDesc.CheckSupported ()

Can XmlSerializer do only trivial tasks? Or am I missing something? They talk about custom serialization on MSDN. Here is my simplified code example.

using System; using System.Collections.Generic; using System.IO; using System.Xml.Serialization; namespace ConsoleApplication1 { public interface IDoTest { void DoTest(); void Setup(); } internal class TestDBConnection : IDoTest { public string DBName; public void DoTest() { Console.WriteLine("DoHardComplicated Test"); } public void Setup() { Console.WriteLine("SetUpDBTest"); } } internal class PingTest : IDoTest { public string ServerName; public void DoTest() { Console.WriteLine("MaybeDoAPing"); } public void Setup() { Console.WriteLine("SetupAPingTest"); } } internal class Program { private static void Main(string[] args) { TestDBConnection Do1 = new TestDBConnection { DBName = "SQLDB" }; PingTest Do2 = new PingTest { ServerName = "AccTestServ_5" }; List<IDoTest> allTest = new List<IDoTest> { Do1, (Do2) }; // Now I want to serialize my list. // Its here where I get the error at allTest XmlSerializer x = new XmlSerializer(allTest.GetType()); StreamWriter writer = new StreamWriter("mySerializedTestSuite.xml"); x.Serialize(writer, allTest); } } } 
+4
source share
3 answers

XmlSerializer cannot serialize an interface , and by extension it cannot serialize List<> some interface. It can serialize specific types of objects.

It is assumed that you probably want to deserialize objects at some point, and if it only displays information related to this interface, it cannot guarantee that all the necessary data is available to restore the original objects.

This post shows a potential workaround if you can use an abstract base class and explicitly expose all possible types of objects that can appear in a list.

+3
source

I followed the link that StriplingWarrior gave and found this great answer. fooobar.com/questions/467357 / ... from webturner

I changed its implementation and made the Class ListOfToDo class, which implemented both List and IXmlSerializable. It worked! Here is my modified code.

 using System; using System.Collections.Generic; using System.IO; using System.Xml; using System.Xml.Schema; using System.Xml.Serialization; namespace ConsoleApplication1 { public interface IDoTest { void DoTest(); void Setup(); } public class TestDBConnection : IDoTest { public string DBName; public void DoTest() { Console.WriteLine("DoHardComplicated Test"); } public void Setup() { Console.WriteLine("SetUpDBTest"); } } public class PingTest : IDoTest { public string ServerName; public void DoTest() { Console.WriteLine("MaybeDoAPing"); } public void Setup() { Console.WriteLine("SetupAPingTest"); } } public class ListOfToDo : List<IDoTest>, **IXmlSerializable** { #region IXmlSerializable public XmlSchema GetSchema(){ return null; } public void ReadXml(XmlReader reader) { reader.ReadStartElement("ListOfToDo"); while (reader.IsStartElement("IDoTest")) { Type type = Type.GetType(reader.GetAttribute("AssemblyQualifiedName")); XmlSerializer serial = new XmlSerializer(type); reader.ReadStartElement("IDoTest"); this.Add((IDoTest)serial.Deserialize(reader)); reader.ReadEndElement(); //IDoTest } reader.ReadEndElement(); //IDoTest } public void WriteXml(XmlWriter writer) { foreach (IDoTest test in this) { writer.WriteStartElement("IDoTest"); writer.WriteAttributeString("AssemblyQualifiedName", test.GetType().AssemblyQualifiedName); XmlSerializer xmlSerializer = new XmlSerializer(test.GetType()); xmlSerializer.Serialize(writer, test); writer.WriteEndElement(); } } #endregion } internal class Program { private static void Main(string[] args) { TestDBConnection Do1 = new TestDBConnection { DBName = "SQLDB" }; PingTest Do2 = new PingTest { ServerName = "AccTestServ_5" }; ListOfToDo allTest = new ListOfToDo { Do1, (Do2) }; // Now I want to serialize my list. // Its here where I get the error at allTest XmlSerializer x = new XmlSerializer(allTest.GetType()); StreamWriter writer = new StreamWriter("mySerializedTestSuite.xml"); x.Serialize(writer, allTest); writer.Flush(); writer.Close(); //Read it aka deserialize { var xmlSerializer = new XmlSerializer(typeof(ListOfToDo)); var xmlReader = XmlReader.Create(new StreamReader("mySerializedTestSuite.xml")); ListOfToDo readWhatToTest = (ListOfToDo)xmlSerializer.Deserialize(xmlReader); xmlReader.Close(); } } } } 

The output will be as follows:

  <?xml version="1.0" encoding="utf-8"?> <ListOfToDo> <IDoTest AssemblyQualifiedName="ConsoleApplication1.TestDBConnection, ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"> <TestDBConnection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <DBName>SQLDB</DBName> </TestDBConnection> </IDoTest> <IDoTest AssemblyQualifiedName="ConsoleApplication1.PingTest, ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"> <PingTest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <ServerName>AccTestServ_5</ServerName> </PingTest> </IDoTest> </ListOfToDo> 
+1
source

Not sure if this could be the cause of your problem, but in these two examples they use typeof(T) instead of T.GetType()

http://msdn.microsoft.com/en-us/library/71s92ee1.aspx

I cannot serialize a list of objects in C # with XmlSerializer

0
source

All Articles