2015-11-04 65 views
0

奇怪的結果,我創建了一個streamExtension在那裏我可以簡單地序列化和從和到XML文件deserialze流,代碼如下所示:正從我的XML(反)序列化

/// <summary> 
/// Contains the logic for streaming extensions. 
/// </summary> 
public static class StreamExtensions 
{ 
    /// <summary> 
    /// Serialize an object. 
    /// </summary> 
    /// <typeparam name="T">The type of the object that gets serialized.</typeparam> 
    /// <param name="stream">The stream to which the bytes will be written.</param> 
    /// <param name="serializableObject">The object that gets serialized.</param> 
    public static void SerializeObject<T>(this Stream stream, T serializableObject) where T : IXmlSerializable 
    { 
     var xmlTextWriter = new XmlTextWriter(stream, Encoding.UTF8); 
     xmlTextWriter.Formatting = Formatting.Indented; 
     xmlTextWriter.IndentChar = ' '; 
     xmlTextWriter.Indentation = 4; 

     var serializer = new XmlSerializer(typeof(T)); 

     serializer.Serialize(xmlTextWriter, serializableObject); 

     xmlTextWriter.Close(); 
     stream.Close(); 
    } 

    /// <summary> 
    /// Deserialize a stream and return the object. 
    /// </summary> 
    /// <typeparam name="T">The type of the object that returns from the deserialization.</typeparam> 
    /// <param name="stream">The stream which contains the bytes to deserialize.</param> 
    /// <returns>The object recovered.</returns> 
    public static T DeserializeObject<T>(this Stream stream) 
    { 
     var xmlTextReader = new XmlTextReader(stream); 
     var serializer = new XmlSerializer(typeof(T)); 

     var result = (T)serializer.Deserialize(xmlTextReader); 

     xmlTextReader.Close(); 
     stream.Close(); 

     return result; 
    } 
} 

2很簡單(如果我可以這樣說:優雅)序列化和反序列化的方法。

我使用這個類作爲一個測試:

/// <summary> 
/// A serializable class for testing purposes. 
/// </summary> 
public class SerializableXmlTest : IXmlSerializable 
{ 
    #region Fields 
    private string mTestString = string.Empty; 
    #endregion 

    #region Properties 
    /// <summary> 
    /// Gets or sets the configuration for this simulation. 
    /// </summary> 
    /// <value>The configuration for this simulation.</value> 
    public string TestString 
    { 
     get 
     { 
      return mTestString; 
     } 

     set 
     { 
      mTestString = value; 
     } 
    } 
    #endregion 

    #region XML serialization region 
    /// <summary> 
    /// Write the extra information to an XML stream. 
    /// </summary> 
    /// <param name="writer">Writer to write to.</param> 
    public void WriteXml(XmlWriter writer) 
    { 
     writer.WriteStartElement(MethodBase.GetCurrentMethod().DeclaringType.Name); 
     writer.WriteAttributeString("TestString", this.TestString); 
     writer.WriteEndElement(); 
    } 

    /// <summary> 
    /// Read the extra information from an XML stream. 
    /// </summary> 
    /// <param name="reader">Reader to read from.</param> 
    public void ReadXml(XmlReader reader) 
    { 
     if ((reader.MoveToContent() == XmlNodeType.Element) && (reader.Name == MethodBase.GetCurrentMethod().DeclaringType.Name)) 
     { 
      reader.Read(); 
      this.TestString = reader.GetAttribute("TestString"); 
     } 

     reader.ReadEndElement(); 
    } 

    /// <summary> 
    /// This method is reserved when implementing the IXmlSerializable interface. 
    /// </summary> 
    /// <returns>An XmlSchema that describes the XML representation of the 
    /// object that is produced by the WriteXml method and consumed by the 
    /// ReadXml method.</returns> 
    public XmlSchema GetSchema() 
    { 
     return null; 
    } 
    #endregion 
} 

而且這是在我的單元測試代碼:

/// <summary> 
/// Test the stream extension class for normal function. 
/// </summary> 
[Test] 
public void TestStreamExtension() 
{ 
    File.Delete(mFileName); 
    var testObject = new SerializableXmlTest(); 
    testObject.TestString = "Test"; 

    Stream saveFileStream = new FileStream(mFileName, FileMode.OpenOrCreate); 
    saveFileStream.SerializeObject(testObject); 

    Stream openFileStream = new FileStream(mFileName, FileMode.OpenOrCreate); 
    var testObjectClone = openFileStream.DeserializeObject<SerializableXmlTest>(); 
    Assert.IsTrue(testObject.TestString.Equals(testObjectClone.TestString)); 
    } 

,這是ouputted XML文件:

<?xml version="1.0" encoding="utf-8"?> 
<SerializableXmlTest> 
    <SerializableXmlTest TestString="Test" /> 
</SerializableXmlTest> 

但是有幾件事我不明白,至少其中一個肯定是錯的(我認爲)

的第一件事情是我希望我的xml文件,看起來像這樣:

<?xml version="1.0" encoding="utf-8"?> 
<SerializableXmlTest TestString="Test" /> 

但是如果你需要單獨的開始和結束元素我可以理解。

試圖讀取它的第一個元素讀者的土地上(如預期)<SerializableXmlTest>但是,如果我再繼續做時,第二THIG一個reader.Read()reader.ReadStartElement()調試器告訴我這是當前正在閱讀:

{Whitespace, Value="\r\n "}. 

這是從哪裏來的?爲什麼它讀一個新的行字符?很明顯,當我然後使用其他reader.Read()我確實到我的xml文件中的<SerializableXmlTest TestString="Test" />行。

我在做什麼錯?

附: 這可能是明智的告訴你,我改變了serialize和deserialze方法了一下,(他們曾經是工作),但serialize只使用xmlTextWriter而不是XmlSerializer。 Deserialize方法使用流讀取器而不是XmlTextReader。但爲了試圖讓它們一樣,我得到了這個我似乎無法解決的問題。

額外的問題:我應該甚至使用XmlTextReader和作家?我還可以將我作爲方法參數獲得的流傳遞給序列化程序不能嗎?

+0

邊注:使用'using'將使您的序列助手不僅優雅,但也是正確的(並匹配其他人執行)。 –

+0

謝謝,改了:) – Vincent

+0

不要使用'XmlTextWriter' /'XmlTextReader'類。從.NET Framework 2.0開始,建議使用「XmlWriter」/「XmlReader」。使用'XmlWriterSettings' /'XmlReaderSettings'來配置它們。 –

回答

1

有幾件事。

1)與串行

XmlSerializer.Serialize(stream, object) 

故障已經寫入文件,並開始元素的編碼。這就是爲什麼你會得到奇怪的輸出。減少您的WriteXML方法以打開流,並讓序列化程序完成剩下的工作。這將修復您的書面XML文件。

2)的\r\n

讀取目前訪問XML數據的2種方式。NET

  • XmlReader \ XmlWriter
  • XmlFile

當您使用XmlReader你將有一個XML文件的方式更多的機會和方式比較深。這意味着另一方面,有些自動化裝置會迷路。 XmlReader.Read()工作完全正確。首先他發現一個<標誌。所以現在他知道要閱讀,直到他發現>結束標記。然後你告訴他再讀一遍。現在他讀取\r\n標誌。現在他知道他必須停下來,因爲你告訴他只讀1個字符,並且他沒有發現<作爲開始標記。

希望這有助於

+0

有沒有辦法讓序列化不寫入開始和結束元素,但做我自己? – Vincent

+0

我知道你可以創建你自己的映射,然後創建一個串行器。但我認爲這不會改變,序列化程序將寫入所有需要的有效xml文件。實際上是不需要讓序列化程序處理它的原因是什麼?也許有更好的解決方案 –

+0

因爲我也使用抽象類,並且你需要在抽象類列表上面的那些[]標籤來指示那裏有哪些類,或者你需要讀/寫自己的xml。該公司決定不使用標籤,因爲這意味着,每次創建新的派生類時,都需要打開抽象類並在其中添加標籤。我們越需要打開和更改舊文件越好。 – Vincent