2010-12-04 71 views
5

我有大量的對象都共享一個公共基類,我希望截取所有設置屬性值的調用並記錄是否已經爲每個實例設置了這些屬性值。在運行時替換屬性設置器方法

我可以在運行時用反射替換屬性的Set方法嗎?

回答

6

一種方法有使虛擬財產,並在運行時創建通過一個子類反射發射,則重寫性能,加入您的代碼。但是,這是先進的,並且要求您始終確保創建子類(因此代碼中沒有「新」)。

但是;我想知道是否簡單地實現INotifyPropertyChanged並處理事件更簡單。另一種選擇是首先將處理建立到普通課程中。有使這個少重複的某些方面,特別是如果你有一個共同的基類,你可以添加一個

protected void SetField<T>(ref T field, T value) 
{ 
    if(!EqualityComparer<T>.Default.Equals(field,value)) 
    { 
     field = value; 
     // extra code here 
    } 
} 

隨着

private int foo; 
public int Foo { 
    get { return foo; } 
    set { SetField(ref foo, value); } 
} 
+0

這非常接近我現在所擁有的,謝謝。這確實可以完成這項工作,但意味着我必須手動攔截所有呼叫。 – IanNorton 2010-12-06 06:23:07

1

如果您的基類來自ContextBoundObject,您可以在不同的上下文中創建對象(在同一個AppDomain內)並攔截方法調用(這是屬性的屬性),並將自己的消息接收器插入遠程接收器鏈中。

繼承人一例

http://www.codeproject.com/KB/cs/aspectintercept.aspx

+0

這篇文章實在太過分了,但確實強調它可以完成,我會嘗試這個但沒有屬性。謝謝,當我知道更多時,我會發布一些更新。 – IanNorton 2010-12-06 06:28:57

0

在運行時不能直接取代它。如果這個屬性是虛擬的,你可以使用一個DynamicProxy,比如Castle的 http://www.castleproject.org/dynamicproxy/index.html ,爲你創建一個代理類型來擴展你的類型,它的工廠可以用來獲得一個有攔截方法的類。

或者,您可以沿着ContextBoundObject路線或Enterprise Libaries Policy Injection行駛。 http://msdn.microsoft.com/en-us/library/cc511729.aspx

被警告ContextBoundObject比Castle的動態代理慢得多,但是你不必聲明你的方法是虛擬的。策略注入只允許你在調用建議之前或之後插入,所以如果你出於任何原因反對它,你不能停止調用。

如果您可以將此操作作爲後編譯步驟處理,則可以使用PostSharp或Mono.Cecil。

我個人正在使用我自己的動態代理,它允許用代理替換方法,但它幾乎沒有準備好石灰燈。