2009-01-23 158 views
3

序列化時,我想只序列化一個對象一次,然後對該對象的任何引用都應序列化爲對該對象的引用。這是因爲,當我後來反序列化對象時,我想維護這些引用。爲了說明我的目標,下面的代碼應該輸出「序列化後:真」。通過序列化/反序列化維護對象引用

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

回答

2

如果您使用.NET 3或更高版本,您應該使用DataContractSerializer,並設置PreserveObjectReferencestrue

+1

我只是試圖做到這一點,但它不工作,因爲它是隻讀屬性。我在這裏錯過了什麼? – 2012-02-08 01:41:02

0

您將不得不通過提供對象引用以外的對象標識符來實現此目的。

對象的引用本質上就是它的指針。由於您無法直接在安全代碼中操作指針,因此必須給對象一些其他唯一的名稱。

0

不知道這是不是你想聽到的......但是讓我們想想你想做什麼。

您只需要序列化一個對象時: a)您希望將它存儲在某個位置以檢索信息。 b)你想把對象發送給另一個應用程序。

引用不過是指向對象所在的指針。所以在任何一種情況下,你都不能訪問內存,因爲在a)它是爲你的應用程序保留的,而b)它是另一臺機器,它甚至不存在。

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

0

你的代碼示例不會簡單地工作,因爲XmlSerializer不保存參考信息,在序列化過程中它將簡單地將obj的數據寫入流的兩次,這意味着當您反序列化時它將讀取obj的數據作爲兩個不同的實例,它無法知道它們在序列化時引用了同一個實例。使用前面提到的DataContractSerializer應該給你你想要的但注意它使用非標準的xml (請參閱:http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx

+0

謝謝你的鏈接! – CodeChef 2009-01-23 16:06:37