如何序列化包含其他类对象的类(递归序列化?)

时间:2010-01-30 23:44:41

标签: c# .net xml serialization xml-serialization

我该怎么做?或者序列化程序会自动进行递归,并将所有这些子对象序列化为XML吗?

举个例子,如何序列化包含其他类对象的类本身!这是这个问题的核心!

我已经尝试过了,并没有将任何(XML标头除外)输出到目标XML文件。

我的问题是我需要序列化一个只包含List对象的简单类。但是,这些实体也是Lod List对象。 (另一个好处是,如果我可以避免某些组件的序列化,因为有些组件是派生的并且在其中包含字典。)

public void SaveCurrent(string MapFileName)
{
    string MapPath = world_.game_.Content.RootDirectory + "/Maps/" + MapFileName + ".xml";
    StreamWriter MapWriter = new StreamWriter(MapPath);

    Map SavedMap = new Map();
    SavedMap.Entities = world_.Entities;
    XmlSerializer xSerializer = new XmlSerializer(SavedMap.GetType());

    xSerializer.Serialize(MapWriter, SavedMap);
    MapWriter.Close();
}

这是进行序列化的代码片段。

public class Map
{
    internal string MapName;
    internal string MapDescription;
    internal string MapAuthor;
    public List<Entity> Entities = new List<Entity>();
}

这是序列化的类。 如果从同一个程序集调用序列化,内部会被视为公共吗?代码在SavedMap.GetType()函数处抛出异常,我也尝试了typeof(Map),但是没有成功。我想这是因为我需要一些其他方法来处理每个新类(深度序列化)我该怎么做?

另外,我在一些例子中发现,没有接口继承或属性,因此我也没有添加它们,但我打算使用IXmlSerializable,虽然我不知道如何调用另一个WriteXML实现中的序列化。

4 个答案:

答案 0 :(得分:6)

添加Serializable和XmlInclude你的类:

[System.Serializable]
[System.Xml.Serialization.XmlInclude(typeof(Entity))]
public class Map
{
    internal string MapName;
    internal string MapDescription;
    internal string MapAuthor;
    public List<Entity> Entities = new List<Entity>();
}

用法:

System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(Map));
serializer.Serialize(mapWriter, savedMap);

答案 1 :(得分:3)

只要图中的所有对象都是可序列化的,它将序列化整个对象图(对象及其通过公共成员以递归方式公开的任何对象)。不同的序列化程序对可序列化的内容有不同的规则。例如,XmlSerializer需要一个默认的公共构造函数。

此外,XML序列化程序需要能够根据这些类型的类型信息和属性来分辨它将序列化的类型。例如,假设您有一个具有Animal类型属性的类,但在运行时XmlSerializer在那里找到一个类型为Dog的对象。为了支持这一点,您需要使用XmlInclude属性提前告知它需要支持Dog。

为了将对象图的一部分保留在序列化输出之外,您将使用XmlIgnore属性。不同的序列化程序也有不同的属性,包括/忽略等。

希望这有助于澄清一点。您可能还想阅读this topic in MSDN

答案 2 :(得分:2)

您需要多少控制?您始终可以实现IXmlSerializable -

http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx

答案 3 :(得分:2)

关于Josh Einstein提到的类型问题,您不必使用XmlInclude属性:您还可以将类型列表传递给序列化程序(签名为XmlSerializer(Type baseType, Type[] extraTypes))。如果额外类型列表有可能随着时间的推移而增长,则应该这样做。

可以通过对要序列化的对象进行反射或在加载的程序集上启动时反射以获取任何所需类型来完成额外类型的查找。

编辑:原始示例:

public abstract class Animal
{
}

public class Dog : Animal
{
}

public class Cat : Animal
{
}

public static class AnimalSerializer
{
    public static void Serialize(List<Animal> animals, Stream stream)
    {
        List<Type> animalTypes = new List<Type>();
        foreach (Animal animal in animals)
        {
            Type type = animal.GetType();
            if (!animalTypes.Contains(type))
            {
                animalTypes.Add(type);
            }
        }
        XmlSerializer serializer = new XmlSerializer(typeof(List<Animal>), animalTypes.ToArray());
        serializer.Serialize(stream, animals);
    }
}