2012-03-01 5 views
7

私はIDisposableを実装するクラスを使用して、usingステートメントを使ってブロックをストリームに書き出しました。これは、正しいネストを維持し、開始/終了部分の欠落または間違った配置を避けるために役立ちます。C#で(コード例)(XMLなどの)コードブロックを書くために(IDisposable obj = new ...)を使用

基本的に、コンストラクタは、ブロックの開始(例えば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(); 
    } 
} 

使い方は次のようである:

<RootElement DocVersion="123"> 
    <InnerElement> 
     <!-- anything --> 
    </InnerElement> 
</RootElement> 
+2

なぜそれが問題になるはずですか?あなたはUsableXmlElement内のアンマネージドリソースを取得しないので、ファイナライザは必要ありません。私はそう思います... – user1096188

+0

ああ、あなたはWriteValueとWriteAttributeが汎用である必要はありません。 _xwriter.WriteValueは常にオブジェクトパラメータで呼び出されるため、何もしません。 – user1096188

+0

ハムムーム........ – code4life

答えて

2

これに任意の下側にあり、

号デストラクタ(ファイナライザ:

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 
    } 
} 

がで得られました)は避けてくださいいいえ、リソースを持つクラスでさえ、普通は(なくても)良いことができます。

これは正しい要素の入れ子を維持する良い方法ですか?

はい。あなたは参考としてSystem.Web.Mvc.Html.MvcFormを使用することができます。

これらのIDisposableをは「フル」のパターンが正しいが、日付であることをマイクロソフト

が推奨する、洗練されたパターンを実装していません。 「裸の」管理されていないリソースの状況だけを記述します。管理されたリソースのみを処理するための正式な参照は提供されません。

3

私が見ている主な欠点は、例外的にすべてのネストされた終了タグを繰り返し書き込むことを試みるということです(use statementの非標準的な使用を除いて、おそらく "最小の驚きの原則"に違反します) XmlWriterによって投げられました。

少なくとも理論的には、内側の終了タグを書き込んでいる間に例外がスローされ、その後にusingステートメントによって生成されたfinallyブロックに外側の終了タグが正常に書き込まれる可能性があります。これは無効な出力につながります。

+0

"それほど驚きの原則"とは言わずに聞いたことがありません。私は将来、その表現を使用します:) –

1

Dispose()を呼び出さなくても、管理されていないリソースが解放されるように、Microsoftによって使用される複雑なパターンが作成されます。

クラス内でアンマネージリソースを使用することはありません。 C#のusingキーワードを利用するだけで、コードを読みやすく保守しやすくすることができます。私はそれが素晴らしいアプローチだと思っています。私は過去にそれを使っています。

終了タグが正しい位置に書き込まれていることを確認する必要があるので、ファイナライザ構造を使用することは意味がないと思います。ファイナライザが呼び出された時期は決してわからないので、要素を廃棄することを忘れた場合に終了タグが書き込まれるタイミングを確かめることはできません。終了タグが全く書かれていなくても、間違った位置に書かれていなくても、あなたのXML文書はまだまだ混乱するでしょう。

最悪の場合、ファイナライザがDispose()を呼び出すと、XmlWriterは既に破棄されていて、例外が発生する可能性があります。だからファイナライザーはない方がいい。

関連する問題