序列化接口

时间:2011-01-11 15:27:10

标签: c# xml-serialization

我正在尝试运行与此类似的代码:

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;

namespace ConsoleApplication1
{
    [Serializable]
    [XmlInclude(typeof(List<Class2>))]
    public class Class1
    {
        private IList<Class2> myArray;

        public IList<Class2> MyArray
        {
            get { return myArray; }
            set { myArray = value; }
        }

    }

    public class Class2
    {
        private int myVar;

        public int MyProperty
        {
            get { return myVar; }
            set { myVar = value; }
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            XmlSerializer ser = new XmlSerializer(typeof(Class1), new Type[] { typeof(List<Class2>) });
            FileStream stream = File.OpenWrite("Data.xml");
            ser.Serialize(stream, new List<Class1>());
            stream.Close();
        }
    }
}

有人可以向我解释我做错了什么吗?

我得到了:

无法序列化成员.. MyArray ...因为它是一个界面。

XmlInclude不应该解决这个问题吗?

4 个答案:

答案 0 :(得分:14)

没有。您无法序列化界面。永远。它只是告诉你。

界面只不过是对一组行为的描述。它没有说明实例的内容。特别是,虽然实现接口的类的实例必须实现其所有成员,但它肯定具有自己需要序列化的属性。

如何反序列化?

将使用哪个类来反序列化另一端的接口?

答案 1 :(得分:13)

这是我原本倾向于使用的未经测试的阴暗解决方法:

private IList<Class2> myArray;
[XmlIgnore]
public IList<Class2> MyArray
{
    get { return myArray; }
    set { myArray = value; }
}

[XmlElement("MyArray")]
public object MyArraySerializable
{
    get { return MyArray; }
    set { MyArray = value as IList<Class2>; }
}

这将序列化您可能使用的任何列表作为具有type属性的通用对象,该属性将告诉反序列化器对象的实际类型,因此当该对象被反序列化时,它应该再次转换为IList<Class2>。请记住提供界面可能采用的任何类型。


我认为没有理由为什么任何序列化程序都无法序列化这些属性。它与您实际尝试序列化接口不同,您尝试序列化实现某个接口的对象(与抽象子类化差别不大,某些编程语言甚至只能在接口上运行)。

当序列化程序应该序列化该对象它知道该对象实现了该接口时,它真正需要做的就是序列化它并附加type属性(就像序列化抽象类或只是一般的超级课程。

现在反序列化器查看类型,可以检查该对象实际上是否实现了所需的接口,然后将其反序列化为相应的属性。

答案 2 :(得分:9)

或者改为使用DataContractSerializer

答案 3 :(得分:0)

您包含了typeof(List&lt; ...&gt;),但MyArray的类型为IList&lt; ...&gt;这不是明显的数据结构本身,而是更多的占位符来采取一些数据结构。

将MyArray的类型更改为特定类型(例如List),它应该有效。

    private List<Class2> myArray;

    public List<Class2> MyArray
    {
        get { return myArray; }
        set { myArray = value; }
    }