Указанная причина сохранения локальной копии EventHandler
заключается в том, что подсистема управления WPF использует внутренние ссылки, поэтому нам необходимо сохранить ссылку на конкретный объект-делегат, который добавлен в событие CanExecuteChanged
. Если факт, в любое время, когда мы добавляем к любому командному событию подсистемы, мы также должны наблюдать эту практику, как у вас есть для SecurityTypeChanged
.
Короткий ответ на ваш вопрос в том, что canExecuteChangedHandler
может быть статичной, но вы должны быть осторожны, чтобы только инициализировать ее один раз. Причина, по которой он может быть статичным, заключается в том, что все new EventHandler(CanExecuteChanged)
будут делать то же самое, если CanExecuteChanged
является статическим. Причина его инициализации однажды заключается в том, что разные экземпляры разные.
Частная собственность, которая имеет право только для чтения семантики:
static EventHandler canExecuteChangedHandler
{
get
{
if (internalCanExecuteChangedHandler == null)
internalCanExecuteChangedHandler = new EventHandler(CanExecuteChanged);
return internalCanExecuteChangedHandler;
}
}
static EventHandler internalCanExecuteChangedHandler;
, но это работает только если CanExecuteChanged
статична. Если это не так, то удалите квалификаторы static
. В любом случае вы должны быть осторожны, чтобы на самом деле использовать собственность.
В этом конкретном примере, во второй раз, когда AddSecureCommand
называется первым, canExecuteChangedHandler
рискует быть собранным мусором.
Наконец, если это все звучит как черная магия, вот пример кода, чтобы показать, что происходит.
public class Container
{
private WeakReference reference;
public object Object
{
get { return reference.IsAlive ? reference.Target : null; }
set { reference = new WeakReference(value); }
}
}
public class DelegateTest
{
private EventHandler eventHandler;
private Container container1;
private Container container2;
void MyEventHandler(object sender, EventArgs args)
{
}
public DelegateTest()
{
this.eventHandler = new EventHandler(MyEventHandler);
this.container1 = new Container { Object = this.eventHandler };
this.container2 = new Container { Object = new EventHandler(MyEventHandler) };
GC.Collect();
Console.WriteLine("container1: {0}", this.container1.Object == null);
Console.WriteLine("container2: {0}", this.container2.Object == null);
}
}
Это производит этот выход:
container1: False
container2: True
, который указывает, что во время сборки мусора, что второй контейнер имел свою EventHandler
сборку мусора «из-под него». Это по дизайну способ, которым работают слабые ссылки, и объяснение для вас должно содержать ссылку на него самостоятельно.
Я понимаю причину сбора мусора, и я знаю, что должен быть объявлен EventHandler на уровне класса. Проблема, с которой я сталкиваюсь, - это когда я создаю экземпляр класса несколько раз, я получаю нечетное поведение, когда оно статично. – Brady
Я хотел добавить новую строку, и она представила комментарий. Я попытался отредактировать вышеупомянутый комментарий, но, видимо, мне осталось всего 5 минут, чтобы обновить его. Чтобы выработать выше ... Проблема, с которой я сталкиваюсь, - это когда я создаю экземпляр класса (или управления) несколько раз, когда получаю нечетное поведение, когда оно статично. Проведя немного больше исследований, я вижу, что цель делегата EventHandler специфична для экземпляра. В моем случае использование статического события EventHandler вызывает проблемы. Я могу видеть, как могут быть моменты, когда статический EventHandler можно использовать, но я думаю, что это не сработает в моем случае. – Brady
Подводя итог вашей точке: ссылка на обработчик событий может быть статичной, только если статический метод. Вы все равно должны быть осторожны, чтобы не изменять его после того, как вы добавили его в командные события.Я обновлю ответ. –