2011-11-09 105 views
0

我有一個奇怪的問題,很困惑。我想通過電線發送數據集並對其進行序列化。當我反序列化時,我想檢索對象和它的屬性。但是,當我DESERIALIZE(EDITED)時,它似乎失去了與基類相關的子類。我創建了以下類:反序列化時丟失對象

[Serializable] 
    public class DataAttributeColumn : DataColumn, ISerializable 
    { 

     private string attributeName; 

     [DataMember(IsRequired = true)] 
     public string AttributeName 
     { 
      get { return attributeName; } 
      set { attributeName = value; } 
     } 

     public void GetObjectData(SerializationInfo info, StreamingContext context) 
     { 
      info.AddValue("AttributeName", this.AttributeName); 
     } 
    } 

而不是使用列名的DataColumn的,我想擴展它的添加屬性名稱。這一切都工作100%,直到我通過電線發送。

我創建了以下Test類並使用了Binary和DataContract序列化程序。

public class Test 
    { 
     DataSet ds = new DataSet(); 
     DataTable dt = new DataTable(); 
     DataAttributeColumn dac = new DataAttributeColumn(); 

     public void CreateData() 
     { 
      ds.Tables.Add(dt); 
      dac.AttributeName = "MyAttribute"; 
      dt.Columns.Add(dac); 

     } 

     public void SerializeBinary() 
     { 
      DataSet dss = new DataSet(); 

      BinaryFormatter dcs = new BinaryFormatter(); 
      ds.RemotingFormat = SerializationFormat.Xml; 

      string strTempfilePath = "binary.txt"; 
      FileStream fs; 
      using (fs = new FileStream(strTempfilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite)) 
      { 
       dcs.Serialize(fs, ds); 
      } 

      fs = new FileStream(strTempfilePath, FileMode.Open); 
      dss = dcs.Deserialize(fs) as DataSet; 

      DataAttributeColumn dac2 = null; 
      dac2 = dss.Tables[0].Columns[0] as DataAttributeColumn; 

      if (dac2 != null) 
      { 
       Console.WriteLine("YOU DID IT!!!!"); 
      } 
      //Second Serialize 
      using (fs = new FileStream("binary2.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite)) 
      { 
       dcs.Serialize(fs, dss); 
      } 
     } 
     public void SerializeDataContract() 
     { 
      DataSet dss = new DataSet(); 

      Type[] knowntypes = { typeof(DataAttributeColumn), typeof(DataColumn) }; 
      DataContractSerializer dcs = new DataContractSerializer(typeof(DataSet), knowntypes); 
      MemoryStream stream = new MemoryStream(); 
      ds.RemotingFormat = SerializationFormat.Xml; 

      string strTempfilePath = "datacontract.txt"; 
      FileStream fs; 
      using (fs = new FileStream(strTempfilePath, FileMode.OpenOrCreate, FileAccess.ReadWrite)) 
      { 
       dcs.WriteObject(fs, ds); 
      } 

      fs = new FileStream(strTempfilePath, FileMode.Open); 
      dss = dcs.ReadObject(fs) as DataSet; 

      DataAttributeColumn dac2 = null; 
      dac2 = dss.Tables[0].Columns[0] as DataAttributeColumn; 
      if (dac2 != null) 
      { 
       Console.WriteLine("YOU DID IT!!!!"); 
      } 

      using (fs = new FileStream("datacontract2.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite)) 
      { 
       dcs.WriteObject(fs, dss); 
      } 
     } 
    } 

我的目標是創建一個屬性,當我反序列化,我可以從DataColumn中投的對象放回DataAttributeColumn,以獲取「的AttributeName」。

我該怎麼做到這一點?

編輯:反序列化後serializatiion

<DataSet><xs:schema id="NewDataSet" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"><xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true"><xs:complexType><xs:choice minOccurs="0" maxOccurs="unbounded"><xs:element name="Table1"><xs:complexType><xs:sequence><xs:element name="Column1" msdata:**AttributeName="MyAttribute"** type="xs:string" minOccurs="0"/></xs:sequence></xs:complexType></xs:element></xs:choice></xs:complexType></xs:element></xs:schema><diffgr:diffgram xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"/></DataSet> 

和輸出後的輸出:

<DataSet><xs:schema id="NewDataSet" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"><xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true"><xs:complexType><xs:choice minOccurs="0" maxOccurs="unbounded"><xs:element name="Table1"><xs:complexType><xs:sequence><xs:element name="Column1" type="xs:string" minOccurs="0"/></xs:sequence></xs:complexType></xs:element></xs:choice></xs:complexType></xs:element></xs:schema><diffgr:diffgram xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"/></DataSet> 
+0

很難使這個問題的意義。屬性與類型相關聯。你序列化一個對象,而不是一個類型。 –

+0

讓我們這樣,在序列化後,我怎樣才能確保何時我將「dac2 = dss.Tables [0] .Columns [0]」作爲DataAttributeColumn;「。我可以在反序列化之後檢索「dac2.AttributeName」。 – Mage

回答

0

的關鍵是以下行:

Type[] knowntypes = { typeof(DataAttributeColumn), typeof(DataColumn) }; 

你需要使用這些knowntypes每個SerializeDeserialize每次。這樣格式化程序就會知道保存一個合適的實際類,即使包含它的數組是用子類聲明的。檢查你自己的代碼,你在一個地方正確使用它,而不是在其他地方使用它!

+0

我不明白。我在序列化中添加了已知類型。如何在反序列化時添加它?我同時使用BinaryFormatter和DataContractSerializer的原因是爲了測試序列化機制 – Mage

+0

您提出了一個問題,答案是:每次調用Serialize或Deserialize時,都必須傳遞knowntypes變量,其中包含可以出現在數組中的類型列表在序列化期間。你在一個地方通過,但不在其他地方!所以每次都要傳遞它! – zmilojko

+0

您的代碼中存在otehr問題,例如,您不需要DataAttributeColumn定義中的整個GetObjectData業務。最後,如果你簡化了你的問題,你是序列化還是反序列化,還是在反序列化之後檢查對象是否是DataAttributeColumn?最後一個你可以用xxx.GetType()== typeof(DataAttributeColumn)來完成。 – zmilojko

0

讓我們嘗試一種不同的方法。使用XmlSerializer的:

 XmlSerializer serializer = new XmlSerializer(typeof(DataSet)); 
     FileStream fs = new FileStream(yourFilePath, FileMode.Create); 
     XmlWriterSettings Settings = new XmlWriterSettings(); //Please use this! 
     Settings.Indent = true; 
     Settings.IndentChars = " "; 
     Settings.NewLineHandling = NewLineHandling.None; 
     Settings.NewLineChars = "\n"; 
     XmlWriter writer = XmlWriter.Create(fs, Settings); 
     //XmlWriter writer = new XmlTextWriter(fs, Encoding.ASCII); 
     serializer.Serialize(writer, ds); 
     writer.Close(); 
     fs.Close(); 

反序列化使用:

 XmlReader reader = new XmlTextReader(fs); 
     DataSet ds2 = (DataSet)serializer.Deserialize(reader); 
     reader.Close();