INotifyPropertyChanged subscribing to self
I have a class which implements INotifyPropertyChanged. I'm using Simon Cropp's excellent NotifyPropertyWeaver to inject INotifyPropertyChanged code into the properties. However I now need to modify the setters for a bunch of properties to all do the same thing after the set completes. Modifying the setters requires creating backing fields, implementing the get, implementing the set, etc all with identical implementations except the name of the backing field. I just avoided doing all of this by using NotifyPropertyWeaver.
Instead, I could have my class subscribe to it's own PropertyChanged event and handle the post change operation in the event handler. Is this a safe thing to do? I realize I'll have to watch out for infinite recursion resulting in a stack overflow if my operation modifies one of the properties I'm watching. Are there any other issues I need to watch out for?
Here's an example
public class Foo : INotifyPropertyChanged{
public event PropertyChangedEventHandler PropertyChanged;
public Prop1 { get; set; }
public Prop2 { get; set; }
public Prop3 { get; set; }
public Prop4 { get; set; }
public Foo(){
this.PropertyChanged +=
new PropertyChangedEventHandler(Foo_PropertyChanged);
}
private void Foo_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "Prop1":
case "Prop2":
case "Prop3":
DoSomething();
break;
case "Prop4":
DoSomethingElse();
break;
}
}
private void DoSomething()
{
....
}
private void DoSomethingElse()
{
....
}
}
Edit
Joel Lucsy kindly pointed out that I do not need to subscribe to the event. I had been allowing NotifyPropertyWeaver to inject OnPropertyChanged. Instead I could just implement OnPropertyChanged myself to accomplish the same thing.
Updated code:
public class Foo : INotifyP开发者_运维知识库ropertyChanged{
public event PropertyChangedEventHandler PropertyChanged;
public Prop1 { get; set; }
public Prop2 { get; set; }
public Prop3 { get; set; }
public Prop4 { get; set; }
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
switch (propertyName)
{
case "Prop1":
case "Prop2":
case "Prop3":
DoSomething();
break;
case "Prop4":
DoSomethingElse();
break;
}
}
private void DoSomething()
{
....
}
private void DoSomethingElse()
{
....
}
}
For one thing you just implement OnPropertyChanged and not have to use the event.
Second, this is considered bad form. NotifyPropertyWeaver does a lot of checking in the code and detects dependencies between properties. For instance, if you use property A inside the code for property B, NotifyPropertyWeaver will add a second OnPropertyChanged for B inside the code for A to make sure everything is updated.
In short, don't do it that way, type everything out.
I've done this/used code that has done this before and have noticed no great side effects code wise. Depending upon the number of properties you could see a performance hit, but it probably would be minor. What I have noticed is that it is not always immediately clear when looking at the code why effects are happening when you use this pattern. What you have to be careful of is how you are designing your classes. The automatic properties are nice when you are putting together the class quickly, but they can become a hindrance on your over all design. I usually don't use them unless its a quick mock-up of an object or its a very simple object I'm using for transferring data. The question you have to ask yourself is if you are designing your object this way because its the way that best fits your code, program, style, or because you are trying to use a specific feature i.e. automatic properties.
One thing to consider is, are you going to do the same action for every field, or are you going to have different actions? If you have different actions you quickly get a big unwieldy method. If they are the same actions, it probably is easier to manage.
The normal way I implement the INotifyProperty
interface is to create a method that changes the field, performs the notification, and can also take an Action
to perform after the change is made. This avoids having all the big conditional statements and gives fine grain control over actions, but has enough fine grain control to be completely flexible. If I am creating a lot of objects that are related, I also usually just create a base class to inherit all of them from that has this change method as a protected method, so I don't have to re-implement the pattern once per class.
I have added a On_PropertyName_Changed feature to NotifyPropertyWeaver http://code.google.com/p/notifypropertyweaver/wiki/On_PropertyName_Changed
So if you write this
public class Foo : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Prop1 { get; set; }
public string Prop2 { get; set; }
public string Prop3 { get; set; }
public string Prop4 { get; set; }
void OnProp3Changed()
{
}
void OnProp4Changed()
{
}
}
Calls to OnProp3Changed and OnProp4Changed will be injected into the sets of Prop3 and Prop4 respectively.
精彩评论