答案 0 :(得分:1)
保留EventHandler
的本地副本的原因是WPF命令子系统在内部使用弱引用,因此我们需要保留对添加到{{1的特定委托对象的引用事件。事实上,只要我们添加到任何指挥子系统事件,我们也应该像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
垃圾收集“从其下面”。这是设计弱引用的工作方式,对你的解释需要自己保持对它的引用。