【发布时间】:2015-11-04 07:20:09
【问题描述】:
我创建了一个streamExtension,我可以简单地序列化和反序列化来自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));
}
以及输出的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> 但是,如果我随后继续执行reader.Read() 或reader.ReadStartElement(),调试器告诉我它当前正在阅读:
{Whitespace, Value="\r\n "}.
这是从哪里来的?为什么要读取换行符?显然,当我使用另一个 reader.Read() 时,我确实到达了我的 xml 文件中的 <SerializableXmlTest TestString="Test" /> 行。
我做错了什么?
附: 告诉你我稍微改变了序列化和反序列化方法可能是明智的,(它们曾经可以工作)但是序列化只使用了 xmlTextWriter 而不是 XmlSerializer。并且 Deserialize 方法使用流阅读器而不是 XmlTextReader。但是为了尝试使它们相同,我遇到了这个我似乎无法弄清楚的问题。
额外的问题:我是否应该使用 XmlTextReader 和 writer?我也可以将获得的流作为方法参数传递给序列化程序,不是吗?
【问题讨论】:
-
旁注:使用
using将使您的序列化助手不仅优雅而且正确(并匹配其他所有人的实现)。 -
谢谢,改了:)
-
不要使用
XmlTextWriter/XmlTextReader类。从 .NET Framework 2.0 开始,建议改用XmlWriter/XmlReader。使用XmlWriterSettings/XmlReaderSettings配置它们。
标签: c# xml xml-serialization xml-deserialization