关于c#:如何修复循环在序列化时检测到循环引用?

How can I fix circular A circular reference was detected while serializing?

我正在尝试使用下面提供的对象序列化树结构。我需要用对象序列化子对象列表,但我可以不使用父对象而生存(因为我可以在反序列化时修复它)。

我面临的问题是,不管我是否有[XmlIgnore],我仍然会得到这个错误。

A circular reference was detected while serializing an object of type
'DataEntry'

如果我将"parent"属性的"getter/setter"更改为不执行任何操作,则一切正常。

1
2
3
4
5
6
[XmlIgnore]
        public DataEntry Parent
        {
            get { return null; }
            set {}
        }

但我需要在以后的阶段提供这个家长参考。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public class DataEntry
    {
        [XmlIgnore]
        public DataEntry Parent { get; set; }

        public List<DataEntry> Children { get; set; }

        private List<String> mValues = new List<String>();
        public List<String> Values
        {
            get
            {
                return mValues;
            }
            set
            {
                mValues = value;
            }
        }

        private String mName = String.Empty;
        public String Name
        {
            get { return mName; }
            set
            {
                mName = value;
            }
        }

        /// <summary>
        /// Data entry
        /// </summary>
        /// <param name="partent">parent node - if root node give no parent</param>
        /// <param name="name">Name of property</param>
        /// <param name="values">Values for this property</param>
        public DataEntry(DataEntry partent, String name, List<String> values)
        {
            Children = new List<DataEntry>();
            Parent = partent;
            mValues = values;
            mName = name;
        }

        /// <summary>
        /// Add a child to this node
        /// </summary>
        /// <param name="child"></param>
        public void AddChild(DataEntry child)
        {
            Children.Add(child);
        }
    }

任何帮助都将不胜感激。


XML具有树结构(嵌套标记)。您的对象以图形的形式连接(即,使用循环)。

您必须访问图表,找到循环,并通过剪切引用打开它们。一旦获得了图的生成树,就可以将其序列化。

但是被剪裁的引用将丢失。因此,除了生成树之外,您还需要存储对的剪裁引用。

在反序列化之后,您需要反序列化生成树,然后再反序列化被剪裁的其他引用。所以您将通过在对象之间重新建立这些引用来重建它们。

如果可以,尝试通过将图中的循环减少到已经在那里定义的生成树来避免循环。这样,您就不必为了序列化而做所有的工作。

另一方面,删除这些引用可能会影响应用程序的其余部分,因此您可能不想这样做。

另一个注意事项是:设计良好的数据库具有正常的形式(通常是第三种形式,但也有其他形式)。这些概念几乎是相互关联的。

这是一个粗略的伪C指南:

1
2
3
4
5
6
7
8
9
10
11
12
xml = serialize(root)
{
    1. set all parents to null
    2. XML serialize
    3. rebuilt all parents <-- reuse rebuiltParents()
}

root = deserialize(xml)
{
    1. XML deserialize
    2. rebuilt all parents <-- reuse rebuiltParents()
}