2016-04-29 5 views
2

У меня есть ситуация, когда мне нужно сохранить загруженный HttpPostedFile на диск сервера, предоставить полный путь к некоторому коду, который что-то сделает с файлом на диске, а затем удалит файл. Я решил сделать прокси для работы с файлом. Прокси абстрагирует детали сохранения файла на диск и удаления его, если он больше не используется. Я реализовал IDisposable в прокси-сервере, чтобы обработать сохраненный файл как неуправляемый ресурс и убедиться, что он удаляется в какой-то момент. Конечно, каждый раз, когда я пытаюсь реализовать IDisposable, я дважды проверяю шаблон и обнаруживаю десятки, вопросы и статьи по этой теме, охватывающие все самые сложные реализации.Использование IDisposable для удаления файла с диска

Я думаю, что большинство из этих реализаций являются излишними для того, что мне нужно, поэтому я реализовал это гораздо проще. В моем классе не так много; есть только сохранение файла и нескольких общедоступных строк, чтобы разрешить доступ к сохраненному файлу через его путь к файлу. Существует метод Delete для явного удаления файла и метод Dispose для вызова Delete, если клиентский код этого не делает. И, наконец, есть финализатор, который просто вызывает Dispose. Класс запечатан. Нет членов, которые реализуют IDisposable самостоятельно. Нет значительных управляемых ресурсов. По моей оценке, нет необходимости продолжать вмешиваться в сборку мусора, поскольку единственной важной вещью, которая должна произойти, является удаление файла.

Так мои вопросы таковы:

  1. Что плохого в борьбе с сохранением и удалением файла «Темп» в этой моде?
  2. Есть ли проблемы с моей реализацией IDisposable ниже, учитывая, что мне не нужно беспокоиться об очистке управляемых ресурсов.

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

public sealed class TempFileProxy : IDisposable 
{ 
    private bool disposed; 

    public TempFileProxy(HttpPostedFile httpPostedFile) 
    { 
     this.disposed = false; 
     this.FileName = httpPostedFile.FileName; 
     this.Directory = AppSettings("TempFileDirectory"); 
     this.FullPath = [email protected]"{this.Directory}\{this.FileName}"; 

     httpPostedFile.SaveAs(this.FullPath); 
    } 

    ~TempFileProxy() 
    { 
     this.Dispose(); 
    } 

    public string FullPath { get; } 

    public string Directory { get; } 

    public string FileName { get; } 

    public void Dispose() 
    { 
     if (this.disposed) 
     { 
      return; 
     } 

     this.disposed = true; 
     this.Delete(); 
    } 

    public void Delete() 
    { 
     if (File.Exists(this.FullPath)) 
     { 
      File.Delete(this.FullPath); 
     } 
    } 
} 
+3

Этот вопрос может быть применим для [Code Review] (http://codereview.stackexchange.com/help), если (а) ваш код работает по назначению, (b) ваш код является реальным кодом, а не пример кода, и (c) ваш код включен в тело вопроса. Если вы хотите, чтобы экспертная оценка улучшала все аспекты вашего кода, отправьте ее на обзор кода. –

ответ

1

Нет ничего плохого в удалении временных файлов с использованием реализации IDisposable. Однако будьте осторожны при удалении - вы не хотите, чтобы исключение вызывалось во время этой операции (например, файл используется). Кроме того, подавление финализации, если вы уже расположен объект с помощью регулярного Dispose вызова:

~TempFileProxy() { 
    Dispose(false); 
} 

public void Dispose() { 
    Dispose(true); 
} 

private void Dispose(bool disposing) 
{ 
    if (disposing) 
    { 
     GC.SuppressFinalize(this);     
    } 
    if (this.FullPath != null) 
    { 
     try { 
      File.Delete(this.FullPath); 
     } 
     catch { } 
     this.FullPath = null; 
    } 
} 
+0

Это приносит одну большую мысль о IDisposable, которую я никогда не понимал. Если я не хочу очищать управляемые ресурсы в Dispose, не могу ли я просто не разбираться с ними, а не подавлять финализатор и позволять сборку мусора заботиться о нем всякий раз, когда он сочтет нужным?По-видимому, ответ отрицательный, поскольку ни один пример не показывает этого, но я не понимаю, почему это невозможно сделать таким образом. – bubbleking

+0

Почему есть финализатор на первом месте? Потому что если пользователь вашего класса _forgot_ вызывается Dispose - мы собираемся удалить файл, когда .NET будет мусор собирать экземпляр вашего класса, это причина _only_, чтобы иметь финализатор в вашем случае. Теперь, если пользователь не забыл вызывать Dispose, вызывающий финализатор бесполезен (даже если финализатор абсолютно ничего не делает, поскольку он назвал все еще значительными эксплуатационными расходами), поэтому мы говорим GC, чтобы его подавить. Обратите внимание, что IDisposable - это просто удобный способ сообщить пользователю этого класса, что у вас есть некоторые ресурсы, это ничего не обеспечивает. – Evk

+0

Итак, что происходит в случае вызова Dispose, Finalizer подавляется, но я не устанавливаю ни один из управляемых ресурсов в null в методе Dispose? Будет ли FullPath и другие строки просто задерживаться навсегда и никогда не будут собираться мусором? – bubbleking

1

У меня есть несколько проблем здесь:

1) У меня были проблемы с File.Exists неудовлетворительного на некоторых внешних устройствах. Я дошел до того, что просто пытаюсь использовать этот файл и поймаю исключение, если оно будет выброшено.

2) Файл.Delete может бросить. 2a) Файл используется чем-то. 2b) Там есть фантомный замок. (Windows 8 XPS viewer, я смотрю на вас!) 2c) Проблемы с сетью.

 Смежные вопросы

  • Нет связанных вопросов^_^