我已经开始使用实现IDisposable的类来使用using语句在流中写入块。这有助于保持正确的嵌套并避免丢失或错误放置起始/终止部件。
基本上,构造函数写入块的开头(例如打开XML标记),Dispose()结束(例如关闭XML标记)。示例是下面的UsableXmlElement(它适用于大型XML,因此内存中的LINQ to XML或XmlDocument不是选项)。
但是,这些IDisposable并未实现Microsoft推荐的复杂模式,使用Destructor / Finalizer,单独的Dispose(bool)方法和GC.SuppressFinalize()。 Dispose只是简单地写出end元素,就是这样。
是否存在任何不利因素,或者这是保持元素正确嵌套的好方法?
class UsableXmlElement : IDisposable
{
private XmlWriter _xwriter;
public UsableXmlElement(string name, XmlWriter xmlWriter)
{
_xwriter = xmlWriter;
_xwriter.WriteStartElement(name);
}
public void WriteAttribute<T>(string name, T value)
{
_xwriter.WriteStartAttribute(name);
_xwriter.WriteValue(value);
_xwriter.WriteEndAttribute();
}
public void WriteValue<T>(T value)
{
_xwriter.WriteValue(value);
}
public void Dispose()
{
_xwriter.WriteEndElement();
}
}
用法是这样的:
var xWriter = new XmlWriter(...)
using(var rootElement = new UsableXmlElement("RootElement", xWriter)
{
rootElement.WriteAttribute("DocVersion", 123)
using(var innerElement = new UsableXmlElement("InnerElement", xwriter)
{
// write anything inside Inner element
}
}
导致:
<RootElement DocVersion="123">
<InnerElement>
<!-- anything -->
</InnerElement>
</RootElement>
答案 0 :(得分:3)
我看到的主要缺点(除了非标准使用using语句可能违反&#34;最少意外的原则&#34;)是它会尝试重复写入所有嵌套的结束标记您XmlWriter
抛出的异常事件。
至少在理论上,你可以在编写内部结束标记时抛出异常,然后在&#34;最后&#34;中成功写入外部结束标记。 using语句生成的块。这会导致输出无效。
答案 1 :(得分:2)
这是否有任何不利因素,
没有。无论如何都应该避免使用析构函数(终结函数),即使是拥有资源的类通常也可以(更好)没有。
或者这是保持元素正确嵌套的好方法吗?
是。您可以使用System.Web.Mvc.Html.MvcForm
作为参考。
这些IDisposable没有实现Microsoft推荐的复杂模式
这种'完整'模式是正确但过时的。它仅描述了“裸”非托管资源的情况。不幸的是,没有提供仅用于处理托管资源的官方参考。
答案 2 :(得分:1)
创建microsoft使用的复杂模式是为了确保释放非托管资源,即使您没有调用Dispose()
。
您不在类中使用任何非托管资源。您只需利用C#的using
关键字来使您的代码更具可读性和可维护性。我认为这是一个很好的方法,我也曾在过去使用它。
我认为使用终结器构造甚至没有意义,因为您需要确保结束标记写在正确的位置。您永远不知道何时调用终结器,因此如果您忘记处理元素,则无法确定何时会写入结束标记。无论结束标记是完全写入还是错误位置,您的Xml文档仍然会混乱。
在最坏的情况下,当终结器调用Dispose()时,XmlWriter可能已被释放,并且您将获得异常。所以最好没有终结者。