2009-11-26 67 views
16

我被告知要使用Reflection.Emit的,而不是PropertyInfo.GetValue /的SetValue,因爲它是這樣更快。 但我並不真正瞭解Reflection.Emit中的內容,以及如何使用它來替換GetValue和SetValue。任何人都可以幫助我嗎?比的GetValue及的SetValue Reflection.Emit的更好:S

+2

咦? Reflection.Emit允許您隨時創建代碼以便稍後執行。但它也更復雜且容易出錯,更不用說很難調試了。您需要描述您正在嘗試使用GetValue/SetValue以及哪些性能要求。爲什麼你首先使用反射? – 2009-11-26 15:35:27

+1

我想他有一些動態加載的對象,並希望訪問該屬性,問題是關於調用GetValue/SetValue還是*生成IL代碼來訪問屬性「硬編碼」*將是更好的事情。我建議使用Reflection.Emit.DynamicMethod嘗試,然後檢查哪一個更快。對於我來說,GetValue/SetValue就足夠了,我只需要生成IL代碼來處理簽名在編譯時未知的事件:) – OregonGhost 2009-11-26 15:42:24

+0

我的用戶反射獲取和設置值的屬性對象(我不知道類型的對象) – Omu 2009-11-26 15:58:11

回答

26

只是一個替代答案;如果你想要的性能,但類似的API - 考慮HyperDescriptor;這款採用Reflection.Emit下(所以你不必),但將自己暴露在PropertyDescriptor API,所以你可以用:

PropertyDescriptorCollection props = TypeDescriptor.GetProperties(obj); 
props["Name"].SetValue(obj, "Fred"); 
DateTime dob = (DateTime)props["DateOfBirth"].GetValue(obj); 

一個代碼行來啓用它,它處理所有的緩存等

+0

你是什麼意思「使用HyperDescriptor每下載「?我只需要獲取屬性,獲取並設置值,這就是全部 – Omu 2009-11-27 07:12:38

+0

我的意思是你需要從代碼項目下載HyperDescriptor組件並啓用它,如頁面所示(幾種不同的方式)。 *沒有* HyperDescriptor這是突出榮耀的反思; HyperDescriptor攔截TypeDescriptor並用動態IL替換反射代碼。 – 2009-11-27 07:35:44

+1

這是令人困惑,我同意;在沒有HyperDescriptor的情況下,相同的代碼可以很好地工作,但是如果沒有HyperDescriptor,它的速度會慢很多/(〜100x)。任何使它工作的問題,讓我知道(這是幾年前,當我寫它,但我仍然記得它的大部分!) – 2009-11-27 07:37:26

1

Reflection.Emit的的目的是從PropertyInfo.Get /的SetValue的完全不同。通過Reflection.Emit,您可以直接發送IL代碼,例如動態編譯的程序集,並執行此代碼。當然,這段代碼可以訪問你的屬性。

我嚴重懷疑,這將是更快那麼到底使用的PropertyInfo,並且它不是爲了這個目的要麼做。例如,您可以使用Reflection.Emit作爲小編譯器的代碼生成器。

1

使用Reflection.Emit的似乎有點過於「聰明」,以及一個不成熟的優化。如果您分析您的應用程序,你發現的GetValue /的SetValue反思是瓶頸,那麼你可以考慮優化,但可能不會即使這樣......

11

使用PropertyInfo.GetValue /的SetValue

如果你有性能問題緩存PropertyInfo對象(不重複調用的getProperty)

如果 - 且僅當 - 利用反射的是你的應用程序的性能瓶頸(如看到一個分析器)使用Delegate.CreateDelegate

如果 - 並且確實只有在 - 如果 - 你完全確信閱讀/寫作t他的價值觀仍然是最糟糕的瓶頸,現在該開始學習運行時生成IL的有趣世界了。

我真的懷疑這是值得的,每一個級別都會增加代碼的複雜度,然後提高性能 - 只有在必須的時候纔會這樣做。

如果以性能運行時的訪問是您的性能瓶頸,它可能會更好的編譯時間訪問會(很難的時間是在同一時間通用和超高性能)。

+0

但可行:http:// www。 codeproject.com/KB/cs/HyperPropertyDescriptor.aspx – 2009-11-26 16:41:36

22

如果您多次獲取/設置相同的屬性,那麼使用某些構建類型安全方法確實會比反射更快。但是,我建議使用Delegate.CreateDelegate而不是Reflection.Emit。這樣做更容易,而且速度仍然非常快。

我已經在我的Protocol Buffers的實現中使用這一點,它取得了巨大的差異VS PropertyInfo.GetValue/SetValue。正如其他人所說,只有在證明最簡單的方法太慢之後才能做到這一點。

我有一個blog post與更多的細節,如果你決定沿着CreateDelegate路線。

+0

非常有趣 - 我試着創建一個委託給FieldInfo.SetValue,它完全沒有改變。實際上很明顯,因爲我所做的只是改變函數的調用方式,而函數本身就很慢。 那麼你是如何獲得這種性能提升的呢?我沒有運氣在您的博客文章中找到關於它的信息(也許我只是失明:-D) – Steffen 2009-12-14 18:26:59

+0

只需重新閱讀您的博客文章,並發現了GetGetMethod和GetSetMethod部分,顯然我*之前是失明的。 無論如何,這顯然解釋了速度差異,但是對於FieldInfos,我仍然處於黑暗中:-S 但我期待着Marcs的例子:-) 只是想讓你知道我發現你做了什麼通過代表加速事情。 – Steffen 2009-12-14 21:19:20

+1

乾杯(+1) - 我只是用這個想法在一些反射填充類中保存.1s - .8s每頁:-) – Keith 2010-02-02 10:56:23