2011-11-09 36 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();