我无法使用XmlSerializer序列化C#中的对象列表

时间:2013-03-30 20:09:10

标签: c# xml-serialization xmlserializer

我有一个接口IDoTest的许多测试工具的列表,我想存储在一个文件中。我也想从这个文件中读取。

简单地使用 XmlSerializer 将对象存储在我的IDoTest列表中似乎很自然。但是,当我这样做时,我得到一个模糊的我很抱歉我不能在System.Xml.Serialization.TypeDesc.CheckSupported()

附近做错误

XmlSerializer只能做琐碎的工作吗?或者我错过了什么?他们在MSDN上谈论custom serialization。 这是我的简化代码示例。

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); 

        }
    }
}

3 个答案:

答案 0 :(得分:3)

XmlSerializer无法序列化interface,并且通过扩展,它无法序列化某个接口的List<>。它只能序列化具体的对象类型。

假设您可能希望在某个时刻反序列化对象,如果它只输出与该接口有关的信息,则无法保证所有必要的数据都存在于重建原始对象。

This post显示了一个潜在的解决方法,如果您能够使用抽象基类并明确提供可能出现在列表中的每种可能类型的对象。

答案 1 :(得分:1)

我按照StriplingWarrior给出的链接找到了这个优秀的答案。来自https://stackoverflow.com/a/15089253/648076

webturner

我改变了他的实现,并创建了一个实现List和IXmlSerializable的类类ListOfToDo。那很有效! 这是我改变的代码。

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();
            }


        }
    }
}

输出将是:

    <?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>

答案 2 :(得分:0)

不确定这是否是导致问题的原因,但在这两个示例中,他们确实使用typeof(T)代替T.GetType()

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

I can't serialize a list of objects in C# with XmlSerializer