4

PDF ファイルの操作を行うサードパーティ コンポーネントがあります。操作を実行する必要があるときはいつでも、ドキュメント ストア (データベース、SharePoint、ファイル システムなど) から PDF ドキュメントを取得します。少し一貫性を持たせるために、PDF ドキュメントをbyte[].

このサードパーティ コンポーネントは、使用する必要があるメイン メソッドの 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. メソッドのusing句はAddFileToManipulate()冗長で不要ですか?
  2. オブジェクトのDispose()メソッドで問題なくクリーンアップできていますか?
  3. これは の「許容される」使用法MemoryStreamですか? 一度にメモリ内に非常に多くのファイルがあるとは思っていません...おそらく合計1〜10のPDFページで、各ページは約200KBです。ASP.NET サイトをサポートするサーバー上で実行するように設計されたアプリ。
  4. コメント/提案はありますか?

コードレビューをありがとう:)

4

4 に答える 4

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

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

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

はい、しかしあなたは人生を必要以上に難しくしています。これを試して:

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

これも同様に機能し、はるかに簡単です。オブジェクトを破棄しても、オブジェクトは削除されません。オブジェクトの内部の管理されていないリソースを解放するように指示されるだけです。この方法でオブジェクトに対してdisposeを呼び出すことは問題ありません。オブジェクトは、コレクション内で収集されないままになります。これを実行してから、リストを1回でクリアできます。

  1. これはMemoryStreamの「許容可能な」使用法ですか?一度にメモリ内に非常に多くのファイルがあるとは予想していません...おそらく合計1〜10ページのPDFページで、各ページは約200KBです。ASP.NETサイトをサポートするサーバーで実行するように設計されたアプリ。

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

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

ファイナライザーを実装します。IDisposableを実装するときはいつでもそれは良い考えです。また、Disposeの実装を標準の実装に作り直すか、クラスを封印済みとしてマークする必要があります。これを行う方法の詳細については、この記事を参照してください。protected virtual void Dispose(bool disposing)特に、 Disposeメソッドとファイナライザーの両方が呼び出すよう にメソッドを宣言する必要があります。

于 2009-03-19T07:32:18.847 に答える
2

Using が何をするのかを誤解しているように思えます。

置き換えるのは単なる構文糖です

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

AddFileToManipulate での使用は冗長です。PdfDocumentManipulator のコンストラクターでメモリ ストリームのリストを設定し、PdfDocumentManipulator の dispose メソッドですべてのメモリ ストリームに対して dispose を呼び出します。

于 2009-03-19T02:00:04.510 に答える