2

我对这种方法的细节很感兴趣。如何以及通过什么来跟踪财产的价值变化?

4

2 回答 2

4

Andrew Smith 有一篇很酷的博客文章,我认为它对你有帮助。

我看到的解决方案是访问 PropertyDescriptor并使用它的AddValueChanged方法来提供一个 EventHandler在属性发生变化时接收通知。有时,回复会DependencyPropertyDescriptor 直接提及/使用,但它是同一件事,因为它只是一个派生的 PropertyDescriptor,它提供有关它所代表的基础 DependencyProperty 的附加信息。您可以通过几种方式获取此属性描述符,但最常见的是从 TypeDescriptor.GetProperties 方法或使用 DependencyPropertyDescriptor.FromProperty 获取它。

这种方法的问题是它会根您的对象,因此它永远不会被 GC 收集. 已经有很多关于挂钩事件(尤其是静态事件)如何使您的对象植根的讨论,所以我不会在那里详细介绍。虽然在这种情况下您似乎没有挂钩静态事件,但实际上您是。当您将处理程序添加到属性描述符时,该属性描述符会将委托存储在一个哈希表中,该哈希表由您要挂钩其属性的对象作为键控。委托/处理程序基本上是指向对象上的方法的指针(如果是静态方法,则没有对象),因此这意味着属性描述符具有对您的对象以及您正在查看其值的对象的引用(因为是哈希表的关键)。

于 2012-12-10T08:33:09.620 回答
1

PropertyDescriptor是一个抽象类,因此对于如何触发值更改事件可能有很多答案,具体取决于您手头的具体实现。但可能一个常见的情况是通过反射PropertyDescriptor获得a ,在这种情况下,我认为返回了一个对象。ReflectPropertyDescriptor

查看该类的参考源SetValue(),您可以看到该事件仅在调用该方法时引发。据我了解,这意味着如果您只是这样做:

someObject.A = "value";

不会ValueChanged引发任何事件。

但是,如果您获得了ReflectPropertyDescriptorfor 属性A并使用它来间接设置值,如下所示:

descriptor.SetValue(someObject, "value");

这将引发事件。

从另一个角度考虑这一点,当设置属性值时,CLR 似乎无法在更基本的级别上实际引发事件。我假设这样的事情会产生通常不受欢迎的开销,因为每次在任何属性上设置值时,即使没有事件订阅者,每个集合(实际上只是一个函数调用)也必须检查事件订阅者。

于 2021-02-18T22:05:12.177 回答