通过Serialize / Deserialize维护对象引用

时间:2009-01-23 15:00:41

标签: .net serialization

序列化时,我想只对序列化一个对象,然后对该对象的任何引用都应序列化为对象的引用。这是因为,当我稍后反序列化对象时,我想保留这些引用。为了说明我的目标,下面的代码应该输出“After Serialization:true”。

class Program
{
    static void Main(string[] args)
    {
        MyObject obj = new MyObject() { Name = "obj" };
        MyObject[] myObjs = new MyObject[]
        {
            obj, obj
        };

        Console.WriteLine("Object Refs Equal?");
        Console.WriteLine(string.Format("Before Serialization: {0}",
            object.ReferenceEquals(myObjs[0], myObjs[1])));

        XmlSerializer toXml = new XmlSerializer(typeof(MyObject[]));
        using (FileStream toFile = File.Create(@"C:\foo.xml"))
        {
            toXml.Serialize(toFile, myObjs);
        }

        XmlSerializer fromXml = new XmlSerializer(typeof(MyObject[]));
        using (FileStream fromFile = File.OpenRead(@"C:\foo.xml"))
        {
            MyObject[] deserialized = (MyObject[])fromXml.Deserialize(fromFile);

            Console.WriteLine(string.Format("After Serialization: {0}",
            object.ReferenceEquals(deserialized[0], deserialized[1])));
        }

        Console.ReadLine();
    }
}

[Serializable]
public class MyObject
{
    public string Name { get; set; }
}

4 个答案:

答案 0 :(得分:2)

如果您使用的是.NET 3或更高版本,则应使用DataContractSerializer并将PreserveObjectReferences设置为true

答案 1 :(得分:0)

您必须通过提供除对象引用之外的对象标识符来实现此目的。

对象的引用本质上是它的指针。由于无法直接在安全代码中操作指针,因此必须为对象提供其他唯一名称。

答案 2 :(得分:0)

不确定这是否是您想要听到的......但是,让我们考虑一下您想要做什么。

您只需要在以下情况下序列化对象:  a)您希望将其存储在后者的某个位置以检索信息。  b)您希望将对象发送到另一个应用程序。

引用只不过是指向对象所在位置的指针。所以在任何一种情况下你都无法访问内存,因为a)它是为你的应用程序保留的,而b)它是另一台机器,它甚至不存在。

http://en.csharp-online.net/Glossary:Definition_-_Reference_type

答案 3 :(得分:0)

你的代码示例不能简单地工作,因为XmlSerializer不保存参考信息,在序列化过程中它只会将obj的数据写入流两次,这意味着当你反序列化时它会读取obj的数据为两个不同的实例,它无法知道它们在序列化时引用了同一个实例。使用前面提到的DataContractSerializer应该给你你想要的,但请注意它使用非标准的xml (见:http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx