简体   繁体   中英

How does PropertyDescriptor.AddValueChanged work?

I'm intersted in the details of this method. How and by what are property's value changes being tracked?

Andrew Smith has a cool blog post about it which I think it can be helpful for you.

The solution that I have seen given for this is to get to the PropertyDescriptor and use its AddValueChanged method to provide an EventHandler to receive a notification when the property has changed. Sometimes, the reply will mention/use DependencyPropertyDescriptor directly but its the same thing since that is just a derived PropertyDescriptor that provides additional information about the underlying DependencyProperty it represents. You can get to this property descriptor in a few ways but the most common are to get it from the TypeDescriptor.GetProperties method or using the DependencyPropertyDescriptor.FromProperty.

The issue with this approach is that it will root your object so it will never get collected by the GC . There have been plenty of discussions about how hooking events (particularly static events) can root your object so I won't go into great detail there. While it does not seem that you are hooking a static event in this case, in essence you are. When you add a handler to a property descriptor, that property descriptor stores the delegate in a hashtable keyed by the object whose property you are hooking. A delegate/handler is basically a pointer to a method on an object (or no object if its for a static method) so that means the property descriptor has a reference to your object as well as the object whose value you are watching (since that is the key into the hashtable). The property descriptors themselves are cached statically so the hashtable is kept around and therefore your object and the one you are watching are as well.

PropertyDescriptor is an abstract class, so there are presumably many answers to how the value changed event is fired depending on the specific implementation you have at hand. But probably a common case is when a PropertyDescriptor has been acquired through reflection , in which case I think an object of ReflectPropertyDescriptor is returned.

Looking in the reference source for that class, you can see that the event is raised ONLY when the SetValue() method is called. To my understanding this means that if you simply did this:

someObject.A = "value";

there would be no ValueChanged event raised.

However if you got the ReflectPropertyDescriptor for property A and used it to indirectly set the value, like this:

descriptor.SetValue(someObject, "value");

that would raise the event.

To think about this from another point of view, it seems the CLR has no way to actually raise an event at a more fundamental level when a property value is set. I assume something like that would have overhead that would ordinarily be undesirable because each set (really just a function call) would have to check for event subscribers even if there were none, each time a value is set on any property.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM