Существует ли какой-либо шаблон, с помощью которого потребитель INotifyPropertyChanged может избежать утечек памяти даже в обстоятельствах, когда может быть создано произвольное количество экземпляров потребителя в течение времени жизни конкретного объекта INotifyPropertyChanged, без изменения каких-либо свойств этого объекта(и таким образом уведомления об увольнении)?Для издателя событий возможно реализовать слабые события с некоторой уловкой Отражения;есть ли работоспособный шаблон слабого события на стороне подписчика?
Если в контракте на событие требуется, чтобы издатель события разрешил подписчикам на события отменять подписку в любое время, из любого потока, без блокировки на неопределенный срок, тогда это было бы возможно дляподписчик события должен иметь объекты, которые действительно «заинтересованы» в подписчике, хранить ссылку на объект-оболочку и иметь переопределение объекта-оболочки Finalize (), чтобы сообщить объекту подписчика о необходимости отписаться.К сожалению, даже если подписчик обнаруживает с помощью Finalize (), что он должен отменить свою подписку, в контракте .net Event не требуется, чтобы объекты, публикующие события, позволяли безопасно удалять их из финализатора.Действительно, реализация событий по умолчанию для C # на самом деле небезопасна для вызова из финализатора (текущая реализация получает блокировку для объекта, публикующего подписку; если блокировка использовалась только для подписки и отписки, что не было бы проблемой, но нет гарантии, что блокировка не будет удерживаться для какой-либо другой цели в течение некоторого произвольного промежутка времени).Более ранние реализации были хуже: если класс попытался подписаться или отказаться от подписки на свои собственные события, подписка и отмена подписки вообще не были бы поточно-ориентированными.
Если бы знал, что объект INotifyPropertyChanged был каким-то конкретным классом, который реализовалего события в поточно-ориентированном режиме (для подписки получите блокировку, а затем используйте спин-цикл Interlocked.Exchange; для отмены подписки используйте спин-цикл, который получит блокировку, если она доступна, но попытается использовать Interlocked.CompareExchange для блокировкидоступно или нет) можно безопасно удалить обработчик событий в финализаторе.Если бы кто-то знал, что объект будет вызывать событие с некоторой значительной частотой, возможно, можно было бы удалить обработчик из события (хотя я не уверен, что контракт события .net требует, чтобы это тоже было безопасно).Есть ли какое-либо универсальное решение, которое будет работать независимо от того, какой тип реализации INotifyPropertyChanged вы хотите посмотреть?
РЕДАКТИРОВАТЬ - Уточнение
Идея нечто объект отписался бы от своего собственного финализатора, а скорее объекты, которые интересовались эффектами события, будут содержать ссылки на объект-обертку, на который сама обработка событий не будет содержать ссылку.Например, предположим, что целью было подсчитать, сколько раз событие PropertyChanged вызывалось с определенной строкой имени события.Можно иметь объект PropertyChangeCounter, который содержит ссылку на объект PropertyChangeCounter.Internals;последний объект будет содержать подписку на событие и счетчик изменений.Свойство ChangeCount объекта PropertyChangeCounter будет возвращать значение вложенного PropertyChangeCounter.Internals ChangeCount.Объект-обертка получит право на завершение, как только ни один посторонний не будет иметь на него ссылку, и его финализатор сможет вызвать метод отмены подписки в объекте PropertyChangeCounter.Internals.