0

我正在尝试解决与我在如何使用 WriteEndElement 检查元素名称中描述的类似问题

我用内部和外部 XmlWriter 编写了这段代码。这个想法是关闭内部 XmlWriter 也将关闭任何由不完全可靠的第三方库挂起的标签。

var sb = new StringWriter();

using (var xml = XmlWriter.Create(sb, new XmlWriterSettings(){Indent = true}))
{
    xml.WriteStartElement("root");

    using (var inner = XmlWriter.Create(xml))
    {
        inner.WriteStartElement("payload1");

        // simulate ThirdPartyLibrary.Serialise(results, inner) leaving a tag open
        inner.WriteStartElement("third-party-stuff");
    }

    xml.WriteStartElement("payload2");
}

sb.ToString().Dump();

我希望这会产生

<root>
  <payload1>
    <third-party-stuff />
  </payload1>
  <payload2 />
</root>

但是相反,我在应该写的那行得到了一个运行时错误<payload2>

InvalidOperationException
Writer 已关闭或处于错误状态。

为什么我会收到此错误?我没想到关闭内部 XmlWriter 会关闭外部 XmlWriter。

4

2 回答 2

2

在关闭 XmlWriter 内部的代码示例中使用变量名称将释放(外部)XmlWriter xml。这是预期的行为,因为根据这个MSDN 条目处理 XmlWriter“释放 XmlWriter 类的当前实例使用的所有资源”,即它将释放它创建的任何“外部”XMLWriter。

这样的代码会产生代码分析错误CA2202。以下链接中描述了针对此类情况的解决方案。

于 2013-04-05T14:22:36.150 回答
1

查看当您XmlWriter从以下位置创建另一个时会发生什么xml

static void Main(string[] args)
{
    var sb = new StringWriter();
    using (var xml = XmlWriter.Create(sb, new XmlWriterSettings() { Indent = true }))
    {
        xml.WriteStartElement("root");
        using (var inner = XmlWriter.Create(xml))
        {
            Debug.WriteLine(Object.ReferenceEquals(xml, inner));
            //UH OH! Returns true
            inner.WriteStartElement("payload1");
            // simulate ThirdPartyLibrary.Serialise(results, inner) leaving a tag open
            inner.WriteStartElement("third-party-stuff");
        }
        xml.WriteStartElement("payload2");
    }
    sb.ToString().Dump();
}

看?因此,当您处理 时inner,实际上是在处理xml,因为它们是同一个对象。

如果您查看 MSDN:(http://msdn.microsoft.com/en-us/library/77t6e4w3.aspx

返回值类型:

System.Xml.XmlWriter 一个 XmlWriter 对象,它是

包裹在指定的 XmlWriter 对象周围。

所以我假设它使用的是同一个对象。

编辑在这里,您可以使用一个解决方案:

static void Main(string[] args)
    {
        var sb = new StringWriter();
        var sb2 = new StringWriter();

        using (var xml = XmlWriter.Create(sb, new XmlWriterSettings() { Indent = true }))
        {
            xml.WriteStartElement("root");

            using (var inner = XmlWriter.Create(sb2, new XmlWriterSettings() {Indent = true , CloseOutput=true, OmitXmlDeclaration=true}))
            {
                
                inner.WriteStartElement("payload1");
                inner.WriteStartElement("third-party-stuff");
            }

            xml.WriteRaw(sb2.ToString());

            xml.WriteStartElement("payload2");
        }

        Debug.WriteLine(sb.ToString());            
    }
于 2013-04-05T14:33:30.067 回答