2011-10-19 66 views
10

我正在使用Castle DynamicProxy編寫裝飾代理。我需要代理的攔截器攔截唯一的財產寫入(未讀),所以我正是如此檢查方法的名稱:確定MethodInfo實例是否爲屬性訪問器

public void Intercept(IInvocation invocation) 
{ 
    if (invocation.Method.Name.StartsWith("set_") 
    { 
     // ... 
    } 

    invocation.Proceed(); 
} 

現在這工作正常,但我不喜歡我的代理已經成竹在胸的事實如何實現屬性:我想用類似於以下內容替換方法名稱檢查:

if (invocation.Method.IsPropertySetAccessor) 

不幸的是,我的Google-fu失敗了我。有任何想法嗎?

回答

15

你可以檢查屬性是否存在此方法是二傳(未經測試):(啓示Marc's answer to a related question拍攝)

bool isSetAccessor = invocation.Method.DeclaringType.GetProperties() 
     .Any(prop => prop.GetSetMethod() == invocation.Method) 

+1

看起來很不合適 – thepirat000

+0

@ thepirat000:那麼,如果GetSetMethod是O(1),那麼這將是O(n)。這可能不是最佳的(我肯定會贊同任何其他答案同樣可讀,產生更好的性能),但我相信你知道關於過早優化是所有邪惡根源的說法... – Heinzi

+0

我建議你檢查該方法是否具有「get_」前綴(區分大小寫)並將其從方法集合中移除(仍然是O(n)複雜性 - 這相當便宜)。另外,你可以添加'Dictionary '實例來存放已經檢查過的類型,它首先給你O(n)的複雜度,但是之後O(1) –

-4

我想你可以嘗試使用擴展方法: http://msdn.microsoft.com/en-us/library/bb383977.aspx

+0

謝謝,但這是我目前的解決方案。我正在尋找一個不需要我的應用程序就可以瞭解C#編譯器實現細節的知識。 –

+0

他可以使用擴展方法將「IsPropertySetAccessor」方法添加到「MethodInfo」類型,但是他遇到的問題是該方法會比現在更好。 **「我不喜歡這樣的事實,我的代理人對如何實施房產有着深入的瞭解」** –

+2

這個答案相當無益 - 這個問題似乎更多地指向「內部會發生什麼* *確定方法這個「 –

5

沒有這些我知道任何巫術。你可能,也許,剝離set_,尋找一個名稱屬性,並比較MethodInfo實例(invocation.Method)屬性訪問器(GetSetMethod()) - 但是,我不能說實話(不檢查)你是否會得到相同的MethodInfo實例(即使它相同的方法)。

if(method.IsSpecialName && method.Name.StartsWith("set_")) 
{ 
    var prop = typeof (Foo).GetProperty(method.Name.Substring(4), 
      BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); 
    var accessor = prop.GetSetMethod(); 
    bool isSame = accessor == method; 
} 
-1

首先,你可以檢查MethodInfo類的MemberType性能,看它是否是一個Property

現在,你應該嘗試猜測它是一個get還是一個set。如果你不想分析名字(有人可能會命名一個方法「set_Something」),那麼你可以檢查參數。

  • 如果屬性訪問器接受一個參數和返回void是一套
  • 如果屬性訪問器返回一個值,不挑參數,它是一個得到

您可能感興趣的只是第一次檢查

+2

只是出於好奇。那麼這個[]運算符呢?我認爲它允許一個參數。 – dowhilefor

+0

屬性訪問器方法的'MemberType'是'MemberTypes.Method'而不是'MemberTypes.Property'。不管怎麼說,還是要謝謝你。 –

+0

@dowhilefor:好點!!!你能在Reflector/ILDASM中看到結果並告訴我們什麼?我沒有Reflector和帶有此訪問器的程序集,但mscorlib.dll應該充滿它們。 –

0

from MethodInfo object get the MemberType屬性,應該說這是一個Property type所以你應該能夠將它轉換爲PropertyInfo。那個對象暴露了屬性CanWrite,它告訴這是否是一個setter。

+0

嗯,文檔似乎意味着'MemberType'對於'MethodInfo'將是'MemberTypes.Method'對象。 –

+0

嗯,你是對的,我已經忽略了這一點,並期望它是爲屬性創建的MethodInfo對象的MemberTypes.Property,也許這是我現在不知道了現在 – mtijn

+0

我剛剛運行一個測試:'MemberType'一個屬性訪問器方法是'MemberTypes.Method'而不是'MemberTypes.Property',所以這不會飛。無論如何,謝謝。 –

3

我不知道是什麼樣類型的方法是,但如果您可以獲得PropertyInfo,則可以使用IsSpecialName。不幸的是,這不僅告訴該屬性是否是set_或_get,而且如果它是一個重載操作符。

相關問題