INotifyPropertyChanged订阅自我

问题描述:

我有一个实现INotifyPropertyChanged的类。我使用Simon Cropp的优秀NotifyPropertyWeaver将INotifyPropertyChanged代码注入到属性中。不过,我现在需要修改一组属性的setter,以便在set完成后都做同样的事情。修改setters需要创建后台字段,实现get,实现set等等,除了后台字段的名称外,其他实现都是相同的。我只是通过使用NotifyPropertyWeaver来避免所有这些。INotifyPropertyChanged订阅自我

相反,我可以让我的类订阅它自己的PropertyChanged事件并处理事件处理程序中的更改后操作。这是一件安全的事情吗?我意识到如果我的操作修改了我正在观察的某个属性,我将不得不注意导致堆栈溢出的无限递归。我还需要注意哪些其他问题?

下面是一个例子

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() 
    { 
     .... 
    } 
} 

编辑

Joel Lucsy好心指出,我并不需要订阅的事件。我一直在允许NotifyPropertyWeaver注入OnPropertyChanged。相反,我可以自己实现OnPropertyChanged来完成同样的事情。

更新代码:

public class Foo : INotifyPropertyChanged{ 
    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() 
    { 
     .... 
    } 
} 
+0

你可以给一个更真实的世界代码示例,这样我可以更好地理解你在追求什么? – Simon 2011-04-13 22:27:38

我所做的已经这样做过,并明智注意到没有很大的副作用,这个代码/使用的代码。取决于您可以看到性能受到影响的属性数量,但它可能很小。我注意到,在使用这种模式时,为什么会出现效果时,并不总是很清楚。你必须小心的是你如何设计你的课程。自动属性很好,当你把课堂快速放在一起时,它们可能成为你所有设计的障碍。我通常不会使用它们,除非它快速地模拟一个对象或它用于传输数据的非常简单的对象。你必须问自己的问题是,如果你以这种方式设计你的对象,因为它的方式最适合你的代码,程序,样式,或者因为你试图使用特定的功能,即自动属性。

需要考虑的一件事是,你是要为每个领域做同样的动作,还是要采取不同的行动?如果你有不同的行为,你很快就会遇到一个笨拙的方法。如果他们是相同的行为,则可能更容易管理。

我实现INotifyProperty接口的正常方式是创建一个方法,用于更改字段,执行通知,还可以在进行更改后执行Action。这避免了所有大的条件语句,并且对动作进行精细的纹理控制,但是具有足够的细粒度控制来完全灵活。如果我创建了很多相关的对象,我通常也只是创建一个基类来继承所有这些变量方法作为受保护方法,因此我不必每次都重新实现该模式类。

+0

自动属性如何成为设计的障碍?如果你需要添加逻辑/检查到一个getter或setter下来的轨道不会简单地创建一个支持字段,并扩大属性显式实现? – 2011-04-13 02:31:26

+0

@Aydsman我想说的是,如果你围绕他们设计让他们四处走动,他们可以成为一个障碍,不要用后场替换他们。当你不需要后场时,他们很棒(爱他们),但是你不应该因为想要使用后场而避免做出后场。 – 2011-04-13 02:33:39

+0

你能指点我关于上面提到的Action方法的任何信息吗? – 2011-04-13 03:58:26

一方面你只是实现OnPropertyChanged而不必使用事件。

其次,这被认为是不好的形式。 NotifyPropertyWeaver在代码中进行了大量检查并检测属性之间的依赖关系。例如,如果在属性B的代码中使用属性A,则NotifyPropertyWeaver将在A的代码内为B添加第二个OnPropertyChanged,以确保更新所有内容。

总之,不要这样做,输入一切。

+0

好处是,如果我明确实现OnPropertyChanged而不是期望NotifyPropertyWeaver为我完成,那么不需要订阅事件。 – 2011-04-13 03:35:39

+0

我同意NotifyPropertyWeaver将处理属性之间的依赖关系。但是,这不是我想要完成的。 拥有10个类,每个类包含5个属性,它们都具有完全相同的12行实现,除了后台字段名称不仅繁琐,而且容易出错。我希望能够更容易阅读和维护,这就是为什么我使用NotifyPropertyWeaver。 – 2011-04-13 03:48:54

+0

你可以尝试几件事。 PostSharp将为您提供比NotifyPropertyWeaver更大的灵活性。或者你可以尝试我认为被称为T4的内置模板。或者使用片段来生成代码。 – 2011-04-13 04:12:30

我添加了一个On_PropertyName_Changed功能NotifyPropertyWeaver http://code.google.com/p/notifypropertyweaver/wiki/On_PropertyName_Changed

所以,如果你写这

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() 
    { 
    } 
} 

呼叫至OnProp3Changed和OnProp4Changed分别将注入套Prop3和Prop4的。