如何序列化循环引用

本文关键字:引用 循环 序列化 | 更新日期: 2023-09-27 18:17:02

如何序列化相互引用的对象?

public class Item {}
public class Player
{
    Item weapon;
}

这些实例存在于它们自己的某个地方:我在某些类中有一个List<Item> gameobjects,在另一个类中有一个具有List<Item> tileobjects的tile类。

如何序列化循环引用

我是这样解决类似问题的。然后,序列化器类应该跟踪那些已经序列化的对象。例如,将其ID添加到已解析对象的列表中。如果是第一次,应该继续序列化对象,否则可以只写ID。

反序列化时,恢复此ID并在序列化器类中检查该对象是否已被反序列化。如果是,则恢复实际对象并重建引用。否则,反序列化对象并将其ID添加到已反序列化对象的另一个列表中。

例如,你可能有一个像这样的类:

public class GraphSerializer 
{
    Dictionary<string, Node> parsedNodes;
    public void MarkNodeAsParsed(Node node)
    {
        parsedNodes.Add(node.Id, node);
    }
    public bool IsNodeParsed(string id)
    {
        return parsedNodes.ContainsKey(id);
    }
    public Node GetNode(string id)
    {
        return parsedNodes[id];
    }
    [...]
}

现在,当序列化时,你会在伪代码中这样做:

public void Serialize(GraphSerializer serializer, ...)
{
    serializer.Write(node.Id);
    bool isNewNode = !serializer.IsNodeParsed(node.Id);
    if (isNewNode) 
    {
        // Write rest of data
        serializer.Write(node);
        serializer.MarkNodeAsParsed(node);
    }
    // Since this node has already been serialized, we don't need  
    // to serialize any other value as we have already written the node Id
}

那么,反序列化时:

public void Deserialize(GraphSerializer serializer, ...)
{
    string id = serializer.ReadString();
    Node node;
    bool isNewNode = !serializer.IsNodeParsed(node.Id);
    if (isNewNode) 
    {
        // Read rest of data
        node = serializer.Read();
        serializer.MarkNodeAsParsed(node);
    }
    else
    {
        // Node has already been deserialized, so we can just recover it
        node = serializer.GetNode(id);
    }
}