2009-03-19 4 views
3

PDFファイルの操作を行うサードパーティのコンポーネントがあります。操作を実行する必要があるときはいつでも、ドキュメントストア(データベース、SharePoint、ファイルシステムなど)からPDFドキュメントを取得します。少しでも一致させるために、私はPDF文書をbyte[]として渡します。私のコードはList <MemoryStream>を適切にクリーンアップしますか?

このサードパーティコンポーネントは、使用する必要がある主な方法の1つにパラメータとしてMemoryStream[]MemoryStream配列)が必要です。

自分のコンポーネントにこの機能をラップして、アプリケーション内の多くの領域でこの機能を使用できるようにしようとしています。私は基本的に次のように出ている:

public class PdfDocumentManipulator : IDisposable 
{ 
    List<MemoryStream> pdfDocumentStreams = new List<MemoryStream>(); 

    public void AddFileToManipulate(byte[] pdfDocument) 
    { 
     using (MemoryStream stream = new MemoryStream(pdfDocument)) 
     { 
     pdfDocumentStreams.Add(stream); 
     } 
    } 

    public byte[] ManipulatePdfDocuments() 
    { 
     byte[] outputBytes = null; 

     using (MemoryStream outputStream = new MemoryStream()) 
     { 
      ThirdPartyComponent component = new ThirdPartyComponent(); 
      component.Manipuate(this.pdfDocumentStreams.ToArray(), outputStream); 

      //move to begining 
      outputStream.Seek(0, SeekOrigin.Begin); 

      //convert the memory stream to a byte array 
      outputBytes = outputStream.ToArray(); 
     } 

     return outputBytes; 
    } 

    #region IDisposable Members 
    public void Dispose() 
    { 
     for (int i = this.pdfDocumentStreams.Count - 1; i >= 0; i--) 
     { 
      MemoryStream stream = this.pdfDocumentStreams[i]; 
      this.pdfDocumentStreams.RemoveAt(i); 
      stream.Dispose(); 
     } 
    } 
    #endregion 
} 

私の「ラッパー」に呼び出し元のコードは次のようになります。

byte[] manipulatedResult = null; 
    using (PdfDocumentManipulator manipulator = new PdfDocumentManipulator()) 
    { 
     manipulator.AddFileToManipulate(file1bytes); 
     manipulator.AddFileToManipulate(file2bytes); 
     manipulatedResult = manipulator.Manipulate(); 
    } 

上記に関するいくつかの質問:

  1. はですメソッドは冗長で不要なAddFileToManipulate()メソッド内の節ですか?
  2. 私のオブジェクトのDispose()メソッドで何かをクリーンアップできますか?
  3. MemoryStreamの「受け入れ可能な」使用ですか?私はすぐにメモリに非常に多くのファイルを予期していない...おそらく1から10の合計PDFページ、各ページ約200キロバイト。 ASP.NETサイトをサポートするサーバー上で動作するように設計されたアプリケーション。
  4. コメント/ご提案はありますか?あなたはどのような使い方がありません誤解のようなコードレビューのための

おかげで:)

+0

逆方向にカウントしてDisposeでRemoveAtを実行するのではなく、コードを前方に数えて最後にClearを呼び出すだけで簡単になります。 – Dave

答えて

2
  1. AddFileToManipulate()メソッドのusing節は冗長で不要ですか?

さらに悪いことに、それは破壊的です。あなたは基本的にメモリストリームが追加される前に閉じています。詳細については他の答えを見てください。しかし、基本的に最後には破棄しますが、それ以外の時間は避けてください。オブジェクトを使用するたびに、オブジェクトがメソッドを介して他のオブジェクトに「渡された」場合でも、ブロックの最後にDisposeが発生します。

  1. 私のオブジェクトのDispose()メソッドでオブジェクトをクリーンアップできますか?

はい、しかし、あなたは人生を困難にしています。これは、同じようにうまく機能し、はるかに簡単です

 
foreach (var stream in this.pdfDocumentStreams) 
{ 
    stream.Dispose(); 
} 
this.pdfDocumentStreams.Clear(); 

:これを試してみてください。オブジェクトを破棄しても削除されません。オブジェクトを解放して、管理されていない内部リソースを解放します。この方法でオブジェクトを破棄して呼び出すと、オブジェクトはコレクション内で未収集のままです。これを行い、リストを一度にクリアすることができます。

  1. これはMemoryStreamの「許容される」使用ですか?私はすぐにメモリに非常に多くのファイルを予期していない...おそらく1から10の合計PDFページ、各ページ約200キロバイト。 ASP.NETサイトをサポートするサーバー上で動作するように設計されたアプリケーション。

これは状況によって異なります。これらのファイルをメモリに格納するオーバーヘッドが問題を引き起こすかどうかは、あなただけが判断できます。しかし、これはかなり重いオブジェクトになるでしょうから、私はそれを慎重に使用します。

  1. コメント/ご提案はありますか?

ファイナライザを実装します。 IDisposableを実装するたびに良いアイデアです。また、Dispose実装を標準の実装に戻すか、クラスを封印してマークする必要があります。これを行う方法の詳細については、see this article.特に、Disposeメソッドとファイナライザが両方とも呼び出すprotected virtual void Dispose(bool disposing)と宣言されたメソッドが必要です。

+0

ありがとうございました。良い説明とそれらを伝えるために取られる時間/努力を感謝!! – Brian

+0

封印されたニースキャッチ。このプロジェクトの開発者の多くは、とにかく継承チェーンを作ることさえ考えていないでしょう。そして、はい、このオブジェクトは注意して使用されます。それは基本的に "手続き的"なやり方で書かれた機能を基本的に包むという目的を果たすだけです。 – Brian

+0

また、AddFileToManipulate()メソッドでusingステートメントを削除しました。 – Brian

2

それは私には見えます。

それはAddFileToManipulateでご利用が冗長である

MemoryStream ms; 
try 
{ 
ms = new MemoryStream(); 
} 
finally 
{ 
ms.Dispose(); 
} 

を交換するだけ糖衣構文です。私は、PdfDocumentManipulatorのコンストラクタでmemorystreamsのリストを設定し、PdfDocumentManipulatorのdisposeメソッド呼び出しですべてのmemorystreamを破棄します。

+0

ありがとう、私は使用している "使用"を取得します。 – Brian

2

サイドノート。これは実際には拡張メソッドを必要とするようです。

public static void DisposeAll<T>(this IEnumerable<T> enumerable) 
    where T : IDisposable { 
    foreach (var cur in enumerable) { 
    cur.Dispose(); 
    } 
} 

今すぐあなたのDisposeメソッドは、あなたが拡張メソッドを持っているために、3.5フレームワークを必要としない

public void Dispose() { 
    pdfDocumentStreams.Reverse().DisposeAll(); 
    pdfDocumentStreams.Clear(); 
} 

EDIT

になります。彼らは喜んでダウンAddFileToManipulate私をおびえさせる2.0

http://blogs.msdn.com/jaredpar/archive/2007/11/16/extension-methods-without-3-5-framework.aspx

+0

申し訳ありませんが、.NET 2.0については忘れました。拡張メソッドはありません。 : – Brian

+0

また、逆順の理由はアイテムを引き出すことです。 – Brian

+0

拡張メソッドについてはわかりませんでした。もう少し見る必要があります。 – Brian

4

を対象と3.0コンパイラで動作します。

このコードは、配置されたストリームをpdfDocumentStreamリストに追加しています。代わりに、単にストリームを追加する必要があります。

Disposeメソッドでストリームを削除してください。

また、ファイナライザを実装することで、誰かがトップレベルのオブジェクトを処分するのを忘れた場合に備えて、物が確実に処分されるようにする必要があります。

+0

ええ、それは私が考えていたものです。リストに追加された参照カウントはインクリメントされていて、結果として廃棄されていないはずですか?または使用ステートメントの最後にDispose常に呼び出されますか? – Brian

+0

yerp Kieranの回答 –

+0

を参照してください。ファイナライザは、必要に応じてMemoryStreamがすでに独自に実装するためです。 – Dave

関連する問題