在開始本文之前先提兩個疑問:
1、一個.Net程序依賴很多的dll,那個他們是在應用程序啟動的時候全部把所依賴的動態庫全部都加載到應用程序域中的呢還是有選擇的加載呢?
2、當應用程序已經啟動后我們動態加載程序集的話,那么該程序集所依賴的程序集是全部加載還是按需加載呢?
一、分析第一個問題:
創建三個工程ConsoleApplication1是控制台工程,依賴於類庫ClassLibrary1,而ClassLibrary1又依賴於ClassLibrary2工程。
實驗1:ConsoleApplication1引用了ClassLibrary1並通過using ClassLibrary1 但是並沒有調用ClassLibrary1中的成員,打印出應用程序域中加載的程序集,並沒有把ClassLibrary1加載進來
實驗2:把實驗1中的注釋去掉調用ClassLibrary1中Class1.Print()方法,並把斷點設置在該方法上,阻止方法執行,打印出應用程序域中加載的程序集,發現ClassLibrary1已經加載j進來了,而Class1引用了CassLibrary2,但CassLibrary2並沒有加載
進入Class1.Print()方法,打印出應用程序域中加載的程序集,發現ClassLibrary2已經加載j進來了
實驗1、實驗2證明應用程序啟動后clr加載dll是按需加載的,當進入一個方法的時候,即使沒有執行該方法內的任何代碼,都會收集該方法內部用到的所有類型,並加載相應類型所在的dll。
二、分析第二個問題:
還是上面的三個工程,改變依賴關系。ConsoleApplication1不依賴於ClassLibrary1和ClassLibrary2,而ClassLibrary1 依然依賴ClassLibrary2
ConsoleApplication1要通過Assembly.LoadFrom加載ClassLibrary1觀察域中的程序集。
實驗1:ConsoleApplication1項目通過Assembly.LoadFrom的方式手動加載程序集ClassLibrary1.dll,並沒有執行其中的代碼,打印出應用程序域中加載的程序集,發現ClassLibrary1已經加載j進來了,但ClassLibrary1所引用的ClassLibrary2並沒有加載進來
繼續執行通過反射調用Class.Printff方法,打印出應用程序域中加載的程序集,發現ClassLibrary2已經加載j進來了
由此可見動態加載程序集,在沒有調用程序集內部成員的情況下 只加載本身,當調用內部成員的時候加載規則和clr自動加載dll是一樣的。
結論:clr加載程序集是按需加載的,當用到的時候才會把其加載到應用程序域中。