ОБНОВЛЕНИЕ
Я собрал различные ответы отсюда в "окончательный" ответ на новый вопрос.
Оригинальный вопрос
В моем коде у меня есть издатель событий, который существует для всего жизненного цикла приложения (здесь сводится к основным требованиям):
public class Publisher
{
//ValueEventArgs<T> inherits from EventArgs
public event EventHandler<ValueEventArgs<bool>> EnabledChanged;
}
Поскольку этот издатель можно использовать повсюду, я был очень доволен собой для создания этого небольшого вспомогательного класса, чтобы избежать повторной записи кода обработки для всех подписчиков:
public static class Linker
{
public static void Link(Publisher publisher, Control subscriber)
{
publisher.EnabledChanged += (s, e) => subscriber.Enabled = e.Value;
}
//(Non-lambda version, if you're not comfortable with lambdas)
public static void Link(Publisher publisher, Control subscriber)
{
publisher.EnabledChanged +=
delegate(object sender, ValueEventArgs<bool> e)
{
subscriber.Enabled = e.Value;
};
}
}
Он работал нормально, пока мы не начали использовать его на небольших машинах, когда я начал получать случайные:
System.ComponentModel.Win32Exception
Not enough storage is available to process this command
Как оказалось, в коде есть одно место, где элементы управления подписчиков динамически создаются, добавляются и удаляются из формы. Учитывая мое передовое понимание сборки мусора и т.д. (Т. Е. Ни одного, до вчерашнего дня), я никогда не думал проясняться позади меня, так как в подавляющем большинстве случаев подписчики также живут на протяжении всей жизни приложения.
Я немного поиграл с Dustin Campbell WeakEventHandler, но он не работает с анонимными делегатами (не для меня в любом случае).
Есть ли вообще проблема? Я действительно хотел бы избежать необходимости копировать кодовую табличку во всем магазине.
(О, и не беспокойтесь, спрашивая меня, ПОЧЕМУ мы все время создаем и уничтожаем элементы управления, это было не мое дизайнерское решение...)
(PS: это приложение winforms, но мы обновили его до VS2008 и .Net 3.5, следует ли использовать шаблон слабых событий?)
(PPS: Хороший ответ от Rory, но если кто-то может придумать эквивалент WeakEventHandler, который избегает меня, чтобы помнить явно UnLink/Dispose, это было бы круто...)
РЕДАКТИРОВАТЬ Я должен признать, что я работал над этой проблемой, "перерабатывая" контролируемые элементы. Однако обходной путь вернулся, чтобы преследовать меня, поскольку "ключ", который я использовал, по-видимому, не является уникальным (рыдание). Я только что открыл другие ссылки здесь (пробовал это - кажется, слишком слабый), GC очищает делегатов, даже если цель еще жива, та же проблема с s, oɔɯǝɹ answer ниже), здесь (заставляет вас изменить издатель, и на самом деле не работает с анонимными делегатами) и здесь (процитированный как неполный Dustin Campbell).
Мне кажется, что то, что я ищу, может быть семантически невозможным - закрытие предназначено для "зависания даже после того, как я уйду".
Я нашел другое обходное решение, поэтому я буду придерживаться этого, ожидая голос от богов.