【问题标题】:getting strange results from my xml (de)serializer从我的 xml (de)serializer 得到奇怪的结果
【发布时间】: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" />

但如果您需要单独的开始和结束元素,我可以理解。

尝试阅读时的第二个问题 读者登陆的第一个元素是(如预期的那样)&lt;SerializableXmlTest&gt; 但是,如果我随后继续执行reader.Read()reader.ReadStartElement(),调试器告诉我它当前正在阅读:

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

这是从哪里来的?为什么要读取换行符?显然,当我使用另一个 reader.Read() 时,我确实到达了我的 xml 文件中的 &lt;SerializableXmlTest TestString="Test" /&gt; 行。

我做错了什么?

附: 告诉你我稍微改变了序列化和反序列化方法可能是明智的,(它们曾经可以工作)但是序列化只使用了 xmlTextWriter 而不是 XmlSerializer。并且 Deserialize 方法使用流阅读器而不是 XmlTextReader。但是为了尝试使它们相同,我遇到了这个我似乎无法弄清楚的问题。

额外的问题:我是否应该使用 XmlTextReader 和 writer?我也可以将获得的流作为方法参数传递给序列化程序,不是吗?

【问题讨论】:

  • 旁注:使用using 将使您的序列化助手不仅优雅而且正确(并匹配其他所有人的实现)。
  • 谢谢,改了:)
  • 不要使用XmlTextWriter/XmlTextReader 类。从 .NET Framework 2.0 开始,建议改用 XmlWriter/XmlReader。使用XmlWriterSettings/XmlReaderSettings 配置它们。

标签: c# xml xml-serialization xml-deserialization


【解决方案1】:

一些事情。

1) 序列化程序失败

XmlSerializer.Serialize(stream, object)

已经写入了文件的编码和起始元素。这就是为什么你会得到奇怪的输出。减少您的 WriteXML 方法以仅打开流,并让序列化程序完成其余的工作。这将修复您编写的 XML 文件。

2)\r\n的读取

目前在 .NET 中有两种访问 XML 数据的方法

  • XmlReader \ XmlWriter
  • XmlFile

当您使用XmlReader 时,您将有更多的方式访问 XML 文件并且更深入。另一方面,这意味着一些自动化会丢失。 XmlReader.Read() 完全正确。首先,他找到一个&lt; 符号。所以现在他知道阅读直到找到&gt; 一个结束标签。然后你告诉他再读一遍。现在他读到了\r\n 的符号。现在他知道他必须停下来,因为你告诉他只读 1 个字符,而他没有找到 &lt; 一个开始标签。

希望对你有帮助

【讨论】:

  • 有没有办法让序列化不写开始和结束元素,而是自己做?
  • 我知道您可以创建自己的映射,然后从中创建一个序列化程序。但我认为这不会改变,序列化程序将写入有效 xml 文件所需的所有内容。实际上需要不让序列化程序处理的原因是什么?也许有更好的解决方案
  • 因为我也使用抽象类,并且您需要在抽象类列表上方的那些 [] 标记来指示存在哪些类,或者您需要自己读/写 xml。该公司决定不使用标签,因为这意味着,每次创建新的派生类时,都需要打开抽象类并在其中添加标签。我们需要打开和更改旧文件的次数越少越好。
  • Sr 但是对于这一点,我目前没有答案。也许可以教序列化程序这种行为,但从我的角度来看,我会走另一条路。我会使用序列化程序,使用序列化程序编写一个类,然后根据我的需要操作文件/流。
  • 或者也许不使用 xmlSerializer 而只是使用 xmlTextReader 和 writer。
猜你喜欢
  • 2013-08-21
  • 1970-01-01
  • 2022-01-25
  • 2020-10-08
  • 2020-12-25
  • 2010-10-20
  • 2013-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多