2011-04-13 40 views
2

我有一個實現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

回答

0

我所做的已經這樣做過,並明智注意到沒有很大的副作用,這個代碼/使用的代碼。取決於您可以看到性能受到影響的屬性數量,但它可能很小。我注意到,在使用這種模式時,爲什麼會出現效果時,並不總是很清楚。你必須小心的是你如何設計你的課程。自動屬性很好,當你把課堂快速放在一起時,它們可能成爲你所有設計的障礙。我通常不會使用它們,除非它快速地模擬一個對象或它用於傳輸數據的非常簡單的對象。你必須問自己的問題是,如果你以這種方式設計你的對象,因爲它的方式最適合你的代碼,程序,樣式,或者因爲你試圖使用特定的功能,即自動屬性。

需要考慮的一件事是,你是要爲每個領域做同樣的動作,還是要採取不同的行動?如果你有不同的行爲,你很快就會遇到一個笨拙的方法。如果他們是相同的行爲,則可能更容易管理。

我實現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

1

一方面你只是實現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

0

我添加了一個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的。