2013-06-18 90 views
8

我甚至不確定這是否可能,所以如果不是這樣的話可能會道歉。我搜索了相當廣泛,沒有找到我在找什麼。在使用反射的DLL中覆蓋方法

基本上我們有一個由第三方生產的應用程序,完全鈍的是垃圾。我們有一個特殊的問題,並設法使用ILSpy跟蹤DLL中的方法。顯然,我們沒有(也無法獲得)源代碼,所涉及的公司不願意在任何合理的時間尺度上解決問題。

因此,我們調查了各種調查渠道,並沒有提出任何建議。我一直在研究是否可以使用反射來完成,這幾乎是我們得到這個工作的最後希望。概括地說,就是我想要做的是:

  • 因爲現有的DLL具有相同名稱創建一個簡單的類庫
  • 使用反射來從現有的DLL
  • 不知何故導入方法重寫正確的代碼
  • 重建代碼,所以我有一個新的DLL,包含99%的現有DLL的功能,但是使用我的覆蓋代碼提供了正確的功能。

我發現,我的調查TypeBuilder.DefineMethodOverride期間,也從一個StackOverflow的頁面,這似乎相似,但並不完全是我所期待的。

http://msdn.microsoft.com/en-us/library/system.reflection.emit.typebuilder.definemethodoverride.aspx

Is there a way to "override" a method with reflection?

任何意見讚賞!

安德魯

編輯

其他可能的想法,我有是生產含有超控功能的部分類,但似乎沒有可行的兩種。

+0

想知道如果一個基於攔截器的方法可以在這裏工作 - 像Castle DynamicProxy:http://www.castleproject.org/projects/dynamicproxy/ - 顯然你不會完全取代方法調用,但你當然可以攔截/錯誤句柄和調整(哦是的,這取決於如果類有虛擬方法) – Charleh

+0

爲什麼不只是一個類,如你所說,調用第三方類的大多數除了你想重寫的方法之外的東西?或者從該類派生併爲該方法使用另一個名稱?你是否真的需要在1個獨特的DLL裏面?爲什麼不把它分成2個? – ppetrov

回答

6

只有當它是虛擬的時候,你纔可以覆蓋該方法,而不管你是通過反射還是靜態方法來做。我建議使用反編譯器(有很多免費的可用)並修復MSIL中的代碼。然後你可以從MSIL生成一個新的程序集。

+0

是的,我剛剛檢查過,方法不是虛擬的,所以窗外有一個想法。我現在只是檢查反編譯器 - 感謝您的建議。 – Andrew

+0

標誌和publickeytoken如何?它保持不變?! –

+0

如果DLL被簽名(它有一個強名稱),那麼在修改之後,您需要使用強名稱的證書進行簽名。 –

0

我認爲你的第一個想法很好。 如果第三方類別不是sealed,則可以從中派生出來,並添加自己的方法,並使用不同的名稱來糾正錯誤的行爲。 如果你需要它在1個DLL中,你可以使用IlMerge

如果你的第三方類是密封的,你可以在你的新類中有一個這個第三方類的實例,並在需要時調用方法。

但你必須檢查你想「越權」的方法不叫那個庫內,因爲如果是該解決方案將無法工作......

這不是很乾淨,但在編輯圖書館的公司修復問題時,這可能是一個臨時解決方案。

當它被修復時,你只需要重命名你使用的方法,所以它不會花費時間。

0

從你所描述的,我會建議修改原始程序集。過程實質上就是

  • 反編譯裝配成MSIL,C#或任何語言你選擇
  • 修改反編譯組件包括更改
  • 重新編譯使用修改後的源

大會從我看到的Reflexil可以讓你做到這一點,雖然它可能需要你購買Resharper(我沒有自己嘗試過)

或者您可以使用ILDasm給整個集會反編譯單個文件,修改文件,然後使用重新編譯它ILAsm

0

我知道我在有點姍姍來遲這一點,但我會用Charleh同意;如果你有一個表現不好並且不利於替代的類,但至少將其方法聲明爲virtual,那麼你很幸運。下面以引用Castle.CorePatterns

var interceptor = new DelegateInterceptor(proceed: call => 
{ 
    if(ShouldCallProceed(call)) call.Proceed(); 
    else AlternativeLogic(); 
}); 

var generator = new ProxyGenerator(); 
var proxy = generator.CreateClassProxy<UncooperativeType>(interceptor); 

proxy.RubbishMethod(); 

我也採取了LinqPad提供a running sample of this的自由。它顯示了允許攔截的方法(virtual個)和那些沒有攔截的方法之間的區別。它還顯示了一種有用的方法來捕獲異常,但不使用從Patterns使用Try.Do的所有代碼。