PropertyChangedEventManager:AddHandler 与 AddListener

PropertyChangedEventManager: AddHandler vs AddListener

here所述,PropertyChangedEventManager class

Provides a WeakEventManager implementation so that you can use the "weak event listener" pattern to attach listeners for the PropertyChanged event.

订阅 属性 更改的方式有两种:

void AddHandler (INotifyPropertyChanged source, EventHandler<PropertyChangedEventArgs> handler, string propertyName)
void AddListener (INotifyPropertyChanged source, IWeakEventListener listener, string propertyName)

他们最终都调用了同一个方法:

private void AddListener(INotifyPropertyChanged source, string propertyName, IWeakEventListener listener, EventHandler<PropertyChangedEventArgs> handler)

listenerhandler 设置为空。

我需要更改一些具有强事件处理程序(即 source.PropertyChange += handler;)的代码以遵循弱模式。使用 AddHandler 方法很简单。有什么理由更喜欢 AddListener(这需要我实现 IWeakEventListener)?

如果我要编写新代码,优先选择其中一个的原因是什么?

AddHandler(...

只是 .Net 4.5 的一项功能,它可以简化常见情况的代码。 因此,如果符合要求是更好的选择。

.Net4.5 之前只有:

AddListener(...

您可以在以下资源中找到更多信息:

  1. Book - Introducing .NET 4.5:

... it is no longer necessary to create custom WeakEventManager or implement IWeakEventListener...

  1. Blog post - Weak event pattern improvements:

In WPF 4.5 RC, weak event pattern is improved. In addition to listeners, WeakEventManagers also support Handlers. The handlers are defined like event handlers but our classes don't need to implement a particular interface. Plus since there are no hard references maintained, there are no possible memory leaks.


旁注:

根据我的经验,这些解决方案并非万无一失,如果您或您团队中的某个人使用 lambda 表达式作为处理程序,您仍然可能会发生内存泄漏。

当使用 lambda 表达式时,编译器生成匿名 class 作为目标(新生成的 class 包装 lambda 表达式)。 对此 class 的弱引用将立即被 GC 收集。

这里是 Thomas Levesque explanation:

Special case: anonymous method handlers If you're subscribing to the event with an anonymous method (e.g. a lambda expression), make sure to keep a reference to the handler, otherwise it will be collected too soon...

p.s 我最终使用了与 Thomas Levesque 解决方案类似的方法,并且为了保护团队免于使用 lambda 注册,我检查(通过反射)每个处理程序是否为匿名方法。如果是,我会抛出一个异常 - 所以开发人员立即知道这是不可接受的,并更改他们的代码。