2010-12-14 38 views
21

question約IOC容器的用途,中獎提交提到,IoC容器,你可以藉此:Cruft代碼。國際奧委會救援

public class UglyCustomer : INotifyPropertyChanged 
{ 
    private string _firstName; 
    public string FirstName 
    { 
     get { return _firstName; } 
     set 
     { 
      string oldValue = _firstName; 
      _firstName = value; 
      if(oldValue != value) 
       OnPropertyChanged("FirstName"); 
     } 
    } 

    private string _lastName; 
    public string LastName 
    { 
     get { return _lastName; } 
     set 
     { 
      string oldValue = value; 
      _lastName = value; 
      if(oldValue != value) 
       OnPropertyChanged("LastName"); 
     } 
    } 
} 

這樣:

var bindingFriendlyInstance = IoC.Resolve<Customer>(new NotifyPropertyChangedWrapper()); 

問題:

  • 哪個神奇的IoC容器提供了這種善意?
  • 一個實現這個的例子?
  • 有什麼缺點?
  • 在一個具有複雜依賴關係的項目中,當我嘗試將數據綁定應用到這些對象時,我會哭嗎?
+1

我很肯定,答案只是逗你一個「想法」而不是實際的實施。 – 2010-12-14 02:16:19

+1

@chibacity。在那種情況下,Ben Scheirman比我見過的任何妓女都要好。 (當然是在電影裏)。 – AngryHacker 2010-12-14 02:21:54

+0

如果你需要一個沒有邏輯但只有純粹的DTO和屬性改變通知的客戶,最好將它聲明爲一個接口ICustomer,並且用動態代碼生成創建一個具體類並不是什麼大事。 – 2010-12-14 02:34:23

回答

9

關於第二個代碼段工作,NotifyPropertyChangedWrapper肯定將不得不使用反射(或dynamic)以產生類提供與Customer兼容的接口,並實現自動屬性通知。不應該有任何數據綁定問題,但會有一些開銷。

使用動態對象可能看起來像這樣的一個簡單的實現:

public class NotifyPropertyChangedWrapper<T> 
    : DynamicObject, INotifyPropertyChanged 
{ 
    private T _obj; 

    public NotifyPropertyChangedWrapper(T obj) 
    { 
     _obj = obj; 
    } 

    public override bool TryGetMember(
     GetMemberBinder binder, out object result) 
    { 
     result = typeof(T).GetProperty(binder.Name).GetValue(_obj); 
     return true; 
    } 

    // If you try to set a value of a property that is 
    // not defined in the class, this method is called. 
    public override bool TrySetMember(
     SetMemberBinder binder, object value) 
    { 
     typeof(T).GetProperty(binder.Name).SetValue(_obj, value); 
     OnPropertyChanged(binder.Name); 
     return true; 
    } 

    // Implement OnPropertyChanged... 
} 

顯然,消耗這些對象之一的任何代碼將失去任何靜態類型安全。另一種選擇是生成一個實現與被封裝類相同接口的類。網絡上有很多這樣的例子。主要要求是你的Customer必須是interface或者它需要它的所有屬性都是虛擬的。

+0

是的,如果你需要一個沒有邏輯但只有純粹的DTO和roperty變化通知的客戶,最好將它聲明爲一個接口,ICustomer,然後這樣一個構造並不是一個交易來創建一個具體的類動態代碼生成。 – 2010-12-14 02:33:53

+0

無論如何要做到這一點沒有DynamicObject?我在.NET 3.5上。而不是放棄智能感知。 – AngryHacker 2010-12-14 02:36:26

+0

你必須做Pauli說的。我之前做過這個,但代碼很長,而且我沒有它。這裏有一篇文章,其他人這樣做:http://grahammurray.wordpress.com/2010/04/13/dynamically-generating-types-to-implement-inotifypropertychanged/ – Jacob 2010-12-14 02:40:02

2

我從來沒有使用過它,但你可以使用PostSharp創建類似的東西。

3

要以通用方式(即爲任何類實現INotifyPropertyChanged 的單個代碼段)執行此操作,請使用代理。有很多的實現可以通過Castle.DynamicProxyLinFuUnity來完成。這些代理庫在IoC容器中有很好的支持,例如DynamicProxy與Castle Windsor和Unity的攔截(或者其他所謂的)有很好的集成,並且與Unity容器有很好的集成。

1

如果您正在尋找自動生成可綁定對象的特定解決方案,則應查看PropertyChanged.Fody(以前爲NotifyPropertyWeaver)。這將重寫實現INotifyPropertyChanged的類以包含通知代碼。在github頁面上有一個例子。

在我看來,這比使用建議的IOC容器解決方案更簡潔。但是,它是特定於INotifyPropertyChanged綁定的庫,因此不適用作爲常規解決方案,正如您在鏈接問題中討論的那樣。

+0

問題是特別詢問提供該功能的*** IOC容器***。不要打開一個兩年前的問題***,它有一個可接受的答案**,答案並不真正解決問題。 – jgauffin 2013-07-02 10:14:48

+0

我把這個問題解釋爲相關的減少代碼cruft,我從那個角度回答。我認爲國際奧委會的焦點主要是因爲它受到另一個國際奧委會問題的啓發。即使我的答案不使用IOC,我認爲指出其他技術可能更適合實現預期結果也很有價值。此外,[關於元的這個問題](http://meta.stackexchange.com/questions/20524/reviving-old-questions)得出結論,回答老問題是可以的。 – 2013-07-02 13:03:44