C# добавление логики деструктора в статический класс
Есть статический класс для работы с файлом. На время работы программы, ни кто кроме этого класса не "захочет" получать доступ к файлу. Т.к записывать данные в файл придётся часто(очень), то не сильно хочется открывать поток каждый раз, когда внешний код просит записать данные. В итоге пришёл к решению, создать SreamWriter при загрузке приложения, и "освободить" файл, при выгрузке, но столкнулся с проблемой отсутствия у статического класса деструктора. Собственно вопрос, как обойти эту проблему(за исключением пересмотра архитектуры класса, я понимаю, что если поменять статик класс на синглтон, то проблема решится сама собой, мне интересен выход именно из такой ситуации).
Одно из решений, которые приходят в голову, это подписаться на выгрузку домена, и так уже освободить файл, но может есть куда более элегантные решения?
Ответы (2 шт):
Когда вы делаете объект статичным, это означает, что он будет жить считай все время, пока работает ваша программа и это может сыграть злую шутку.
Многие из за лени или незнания делают все статичным, потому что легче что, MyClass.MyMethod(); или var myClass = new MyClass(); myClass.MyMethod();, первое, верно? А как потом из одного класса в другой передать значение? Тоже вопрос у многих и человеку проще сделать "глобальное" значение, которое будет легко доставать из любой точки приложения, но... через некое время они попадают на такие грабли, как у вас, ведь static "вечен")
В вашем случае вы можете сделать 2 вещи:
- Передавать
Streamв нужное место и использовать его там по назначению (например сделайте его публичнымstaticи обращайтесь к нему напрямую, либоpublic static SreamWriter SomeMethod(){...}. - Сделать приватный статичный экземпляр в вашем классе, но наружу выдавайте органы управления, некие методы открытия/закрытия.
Другими словами, вы должны сами контролировать жизнь SreamWriter, но все это простите, бред и костыли и я не советую даже думать про такое. Лучше сделайте обычный класс, реализуйте ему IDisposable и используйте как положено.
Если вам нужно удобство, вам лень постоянно писать var myClass = new MyClass();, то я советую начать использовать IoC контейнеры, где достаточно всего раз поместить тип/объект в контейнер и уже дальше он сам будет следить за его жизнедеятельностью, вам достаточно попросить его в конструкторе нужного класса (DI).
В итоге пришёл к решению, создать SreamWriter при загрузке приложения, и "освободить" файл, при выгрузке, но столкнулся с проблемой отсутствия у статического класса деструктора.
В принципе это и так будет более-менее работать, кроме того, что хвост может остаться незаписанным на диск. Простейший вариант - вместо деструктора явно вызывать некий метод перед завершением приложения, но тут есть нюанс - приложение может не только завершаться корректно, но и падать или зависать. Чтобы даже в таких ситуациях сохранить как можно больше данных, можно их сбрасывать на диск после каждой записи - для этого предназначен метод Flush, который (если я ничего не путаю) надо вызвать сначала на StreamWriter'е, а потом на Stream'е. Ещё есть вариант настроить StreamWriter так, чтобы он не использовал собственный буфер.