首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在使用XML序列化时使用循环引用?

在使用XML序列化时使用循环引用?
EN

Stack Overflow用户
提问于 2010-09-29 00:59:00
回答 3查看 23.1K关注 0票数 22

在尝试使用XMLSerialization序列化对象时,我收到以下异常。

A circular reference was detected while serializing an object of type MyObject}

我知道循环引用是因为ObjectA的childObject可以是ObjectB,而ObjectB的parentObject是ObjectA,但是如果可能的话,我想保留这个引用。有没有办法让这个对象使用XML序列化进行序列化,而不会在序列化过程中丢失任何数据?我对序列化不是很熟悉,所以我希望我可以设置一些属性。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-09-29 01:43:09

根据序列化程序的类型,有几个选项。

如果可以使用DataContractSerializerBinaryFormatter,则可以使用OnSerializedAttribute并将子对象的Parent属性设置为:

代码语言:javascript
复制
[Serializable]
public class Child
{
    public string Foo { get; set; }

    public Parent Parent { get { return parent; } set { parent = value; } }

    // We don't want to serialize this property explicitly.
    // But we could set it during parent deserialization
    [NonSerialized]
    private Parent parent;
}

[Serializable]
public class Parent
{
    // BinaryFormatter or DataContractSerializer whould call this method
    // during deserialization
    [OnDeserialized()]
    internal void OnSerializedMethod(StreamingContext context)
    {
        // Setting this as parent property for Child object
        Child.Parent = this;
    }

    public string Boo { get; set; }

    public Child Child { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        Child c = new Child { Foo = "Foo" };
        Parent p = new Parent { Boo = "Boo", Child = c };

        using (var stream1 = new MemoryStream())
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof (Parent));
            serializer.WriteObject(stream1, p);
            stream1.Position = 0;
            var p2 = (Parent)serializer.ReadObject(stream1);

            Console.WriteLine(object.ReferenceEquals(p, p2)); //return false
            Console.WriteLine(p2.Boo); //Prints "Boo"

            //Prints: Is Parent not null: True
            Console.WriteLine("Is Parent not null: {0}", p2.Child.Parent != null);
        }
    }

}

如果你想使用XmlSerializer,你应该实现IXmlSerializable,使用XmlIgnoreAttribute,并在ReadXml方法中实现大致相同的逻辑。但在这种情况下,您还应该手动实现所有Xml序列化逻辑:

代码语言:javascript
复制
[Serializable]
public class Child
{
    public Child()
    {
    }

    public string Foo { get; set; }

    [XmlIgnore]
    public Parent Parent { get; set; }
}

[Serializable]
public class Parent
{
    public Parent()
    {
    }

    #region IXmlSerializable Members

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        throw new NotImplementedException();
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        //Reading Parent content
        //Reading Child
        Child.Parent = this;
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        //Writing Parent and Child content
    }

    #endregion

    public string Boo { get; set; }

    public Child Child { get; set; }
}
票数 26
EN

Stack Overflow用户

发布于 2010-09-29 01:14:29

如果可以使用DataContractSerializer而不是XMLSerializer,那么可以在DataContract属性上使用IsReference属性。启用此选项将保留引用,以便在反序列化时重新创建它们。

DataContractSerializer也可以序列化为XML,但是与使用较旧的XMLSerializer相比,您对输出的控制要少一些。您可以在此处阅读有关序列化程序的更多信息:http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/

票数 2
EN

Stack Overflow用户

发布于 2010-09-29 01:08:06

将parentObject属性标记为NonSerialized。

https://blog.kowalczyk.info/article/8n/serialization-in-c.html

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3815182

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档