Вопрос

У меня есть сторонний компонент, который выполняет манипулирование файлом PDF. Всякий раз, когда мне нужно выполнить операции, я получаю PDF -документы из хранилища документов (база данных, SharePoint, файловая система и т. Д.). Чтобы сделать вещи немного последовательными, я передаю документы PDF как byte[].

Этот сторонний компонент ожидает 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-страниц, каждая страница около 200 КБ. Приложение, предназначенное для запуска на сервере, поддерживающее сайт ASP.NET.
  4. Есть какие -нибудь комментарии/предложения?

Спасибо за обзор кода :)

Это было полезно?

Решение

  1. Является ли использование пункта в методе AddFileTomAmanipulate () избыточным и ненужным?

Хуже того, это разрушительно. Вы в основном закрываете поток памяти до его добавления. Посмотрите на другие ответы для деталей, но в основном утилизируйте в конце, но не в другое время. Каждое использование с объектом заставляет распоряжение происходить в конце блока, даже если объект «передается» другим объектам с помощью методов.

  1. Я убираю вещи в порядке в методе Dispose () моего объекта?

Да, но вы делаете жизнь труднее, чем должна быть. Попробуй это:

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

Это работает так же хорошо, и намного проще. Утилизация объекта не удаляет его - он просто говорит ему освободить внутренние, неуправляемые ресурсы. Призыв к распоряжению на объект таким образом хорошо - объект остается невозможным, в коллекции. Вы можете сделать это, а затем очистить список одним выстрелом.

  1. Это «приемлемое» использование MemoryStream? Я не ожидаю очень много файлов в памяти одновременно ... вероятно, 1-10 общих PDF-страниц, каждая страница около 200 КБ. Приложение, предназначенное для запуска на сервере, поддерживающее сайт ASP.NET.

Это зависит от вашей ситуации. Только вы можете определить, вызовет ли накладные расходы на наличие этих файлов в памяти проблемы. Это будет довольно тяжелый объект, поэтому я бы тщательно использовал его.

  1. Есть какие -нибудь комментарии/предложения?

Внедрить финализатор. Это хорошая идея, когда вы реализуете Idisposable. Кроме того, вы должны переделать свою реализацию распоряжения на стандартную или отметить свой класс как герметичный. Для получения подробной информации о том, как это должно быть сделано, Смотрите эту статью. В частности, у вас должен быть провозглашенный метод как protected virtual void Dispose(bool disposing) что ваш метод распоряжения и ваш финализатор вызывают оба.

Другие советы

AddFileTomAmanipulate меня пугает.

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

Этот код добавляет распоряженный поток в ваш список PDFDOCumentStream. Вместо этого вы должны просто добавить поток, используя:

   pdfDocumentStreams.Add(new MemoryStream(pdfDocument));

И утилизируйте это в методе утилизации.

Кроме того, вам следует посмотреть на реализацию финализатора, чтобы убедиться, что вещи утилизируются, если кто -то забудет утилизировать объект верхнего уровня.

Мне кажется, что ты неправильно понимаешь, что делает использование.

Это просто синтаксический сахар, чтобы заменить

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

Ваше использование в AddFileTomAmanipulate избыточно. I'd set up the list of memorystreams in the constructor of PdfDocumentManipulator, then have PdfDocumentManipulator's dispose method call dispose on all the memorystreams.

Примечание. Это действительно кажется, что это требует метода расширения.

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

Теперь ваш метод распоряжения становится

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

РЕДАКТИРОВАТЬ

Вам не нужна структура 3.5, чтобы иметь методы расширения. Они с радостью будут работать над компилятором 3.0, нацеленным на 2,0

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top