2

我一直在爲創建目的而創建自己的IoC容器。在問了一些有關它們的問題後,我發現創建一個工廠來「解決」這些對象是最好的解決方案(see third solution here)。用戶Krzysztof Koźmic表明,溫莎城堡實際上可以爲你實現這一點。在沒有創建實現的情況下實現接口(動態代理?)

我一直在讀清楚CW的來源。我知道Resolve何時被調用,它「返回接口」。這個接口如何「截取」調用(因爲後面沒有實現)並將其稱爲自己的方法?

我知道這裏顯然有一些反思技巧,這真是太神奇了。我完全不知道「攔截」是如何完成的。我嘗試在git上冒險嘗試兔子洞,但我迷路了。如果任何人都能指出我正確的方向,那將非常感激。

此外 - 不會創建一個類型的工廠具有對調用代碼內的容器的依賴?在ASP.NET MVC術語中,這就是我所認爲的。

編輯:找到Reflection.Emit ...這可能是什麼用?

EDIT2:我越看越這個,自動創建工廠聽起來越複雜。我可能最終只是堅持重複的代碼。

回答

7

這裏有兩個不同的概念:

  1. 依賴注入僅實例化一個現有的類實現接口。例如,您可能有一個實現IMyServices的MyServices類。 IoC框架爲您提供了多種方式來指定當您請求IMyServices時,它將解析爲MyServices的一個實例。可能會有一些IL Emit魔法繼續建立工廠或輔助方法,但實際實例只是您定義的類。

  2. Mocking允許您實例化一個實現接口的類,而實際上不必編寫該類。正如你所想的那樣,這通常會利用Reflection和IL Emit。通常,發佈的IL代碼非常簡單,將大部分工作委託給用C#編寫的方法。模擬的大部分複雜性與指定方法本身的行爲有關,因爲框架通常允許您使用流暢的語法指定行爲。有些像Moles,只是讓你指定一個委託來實現該方法,儘管Moles可以做其他更瘋狂的事情,比如將調用重定向到靜態方法。


爲了進一步詳細一點,你實際上並不需要使用IL來實現的IoC功能,但是這往往是寶貴的,以避免重複反射調用的開銷,因爲思考是比較昂貴的。 Here是關於Castle Windsor正在做什麼的一些信息。


要回答你的問題,最有用的地方,我發現開始是OpCodes類。這是對IL中可用功能和OpCodes功能如何的一個很好的總結。它基本上是一個基於堆棧的彙編語言(不需要擔心寄存器),但是強類型化並且具有一流的對象符號和概念訪問權限,例如類型,字段和方法。 Here是一個很好的代碼項目介紹IL的基礎知識。如果您有興趣,我還可以向您發送一些我在過去幾年中創建的助手類,這些助手類用於自己的發射碼。

+0

感謝您的評論。我正在嘗試*使用*「嘲笑」我嘗試製作的IoC容器。溫莎城堡使用某種技術來創建一個實現指定界面的「類型工廠」。如果您閱讀我從Krzysztof發佈的鏈接,您會明白我的意思。我不想使用第三方庫,因爲這些都是爲了我自己的學習。你有沒有關於課堂生成的任何資源?編輯:我知道我不需要*使用IL,我只是好奇它是如何完成的。謝謝! :) – TheCloudlessSky 2010-07-05 15:26:15

+0

謝謝你。我要開始閱讀。我可能不會實現這個功能,因爲它看起來非常極端。但是,我要去看看這個,因爲它非常有趣。謝謝! – TheCloudlessSky 2010-07-05 15:39:39

+0

@ TheCloudlessSky,IL很有趣,因爲你可以用它做一些非常強大的事情。但是它的確需要很多工作,而且Emit方法是非常自然的(它們不提供任何包含正確參數的檢查,因此很容易錯誤地創建IL代碼,而這些代碼在運行時無法驗證或爆炸。 )如果你使用它,只要記住peverify.exe是你的朋友。 – 2010-07-05 15:44:52

5

輸入的工廠使用Castle DynamicProxy庫實現。它會動態地生成一個類型來實現接口,並將所有調用轉換爲該類型,通過接口轉發給攔截器。

它不會在您的代碼中產生依賴關係。該界面在您的裝配體中創建,由您控制,您不參考Windsor。在其他程序集(應用程序的入口點)中,您告訴Windsor該界面,並告訴它使其成爲工廠,並且Windsor瞭解您的界面並使用它進行操作。這是控制的倒戈,它的榮耀。

它其實沒有那麼複雜:)

+0

感謝您的回答。那麼,我認爲Castle DynamicProxy庫使用Reflection.Emit? – TheCloudlessSky 2010-07-05 22:32:15

+0

沒關係。我去挖掘DynamicProxy的源代碼,發現了各種各樣的整潔的東西(是的,它使用了Reflection.Emit)。謝謝! :) – TheCloudlessSky 2010-07-05 22:40:02

1

ImpromptuInterface創建基於接口的DLR動態代理。它允許您使用靜態接口進行動態實現。事實上,它甚至有一個基類ImpromptuFactory,它提供了基於接口創建工廠動態實現的起點。

相關問題