使用 XML 序列化时的循环引用? [英] Circular Reference when using XML Serialization?

查看:18
本文介绍了使用 XML 序列化时的循环引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am receiving the following exception when trying to serialize an object using XMLSerialization.

在序列化 MyObject 类型的对象时检测到循环引用}

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

I know the circular reference is because ObjectA can have a childObject of ObjectB and ObjectB's parentObject is ObjectA, however I would like to keep that reference if possible . Is there a way to get this object to serialize with XML Serialization without losing any data during the serialization process? I'm not very familar with serialization so I'm hoping theres some kind of Attribute I could set.

推荐答案

有几个选项取决于序列化器类型.

There are several options depending on serializer type.

如果您可以使用 DataContractSerializerBinaryFormatter 那么你可以使用 OnSerializedAttribute并将子对象的 Parent 属性设置为:

If you could use DataContractSerializer or BinaryFormatter then you may use OnSerializedAttribute and set Parent property for your child object to this:

[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 序列化逻辑:

If you want to use XmlSerializer you should implement IXmlSerializable, use XmlIgnoreAttribute and implemented more or less the same logic in ReadXml method. But in this case you should also implement all Xml serialization logic manually:

[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; }
}

这篇关于使用 XML 序列化时的循环引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆