反序列化时缺少对象

本文关键字:对象 反序列化 | 更新日期: 2023-09-27 18:14:01

我有一个奇怪的问题,我很困惑。我想通过网络发送一个数据集并序列化它。反序列化时,我想检索对象及其属性。然而,当我反序列化(编辑)时,它似乎丢失了与基类关联的子类。我创建了以下类:

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

我想扩展它,添加属性名,而不是为datacoluml使用列名。在我通过网络发送它之前,这一切都是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"。

我怎么来做这件事?

编辑:序列化后的输出

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

反序列化时缺少对象

关键在下面一行:

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

每次需要将这些knowntypes与每个SerializeDeserialize一起使用。这样,格式化程序将知道保存一个正确的实际类,即使包含它的数组是用子类声明的。检查你自己的代码,你在一个地方正确地使用了它,但在其他地方却没有!

让我们尝试不同的方法。使用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();