對接上一文章由於是動態加載指定程序集,會把當前目錄下所有dll都加載進來。如果像sqlite這種第三組件調用了由C、C++非.net語言所以生成的Dll。因為自動生成的原因。會把非C#生成的dll都加載入來導致加載失敗。程序異常。那結果當然不是我們想要的結果了。
怎么避免這類事情的發現。那竟然不能加載所有dll了。那就再細化處理。如果有人把組件模組生成了exe那我們正常來說也應該要處理的。畢竟這也是.net所生成出來的項目。也可以動態加載才是正路。
按上一文章生成輸出的設置。把每個組件模組生成到指定的目錄中去。發下圖(可參考上一文章IDE項目的設置)
優化加載管理類,把組件模組目錄的一級目錄當組件名稱。一個組件占一個目錄以組件模組命名目錄。在加載組件時掃描第一層目錄。通過第一層目錄知道這個組件模組的主程序集。通過命名約束來找到主程序集引用加載。避免加載到非.net生成的dll。然后通過GetReferencedAssemblies方法找出組件模組引用的程序集,把相關的程序集一一加載。
加載組件模組引用第三方.net如圖是第三方寫的json組件。動態加載后再把這個第三方程序集也成功引用入到平台項目中。
然后運行的效果發現出錯了說是調用不成功要引用的第三方組件,因為找不到那個文件。
竟然是找不到文件那要不把那個文件加入到目錄試下。果然是能夠運行起來了。
但這不科學不合理啊。我主程序都沒有引用我怎么能夠把第三方程序集放到根目錄呢。那要是這樣子我們還怎么擴展做組件模組。把所在第三方都放在根目錄以要是項目引用很多第三方那很不好管理。要是管理不當,引用包的版本沖突這是有一定機率發現的。那竟然是找不到調用文件能不能在解釋出錯時返回一個正常的程序集包就行了吧。這理論上也是沒毛病的。在AppDomaing下找到對應的事件。
那就對這事件進行下調用方法。
這段代碼只要在執行組件模組前調用就行了。為了方便就只直寫在Main方法的第一行中方便大家見到。運行效果就不貼圖了。
但如引用sqlite這樣的第三方組件,由於這第三方組件還調用了c寫的SQLite.Interop.dll文件,還區分運行平台是32位系是64位程序。運行輸出效果還是找不到指定文件。還是能夠夠通過把x64\x86這兩個文件目錄復制到根目錄去這就解決問題了。
但這也還是在把東西復制到根目錄啊,有沒有辦法解決這個問題呢。調用非.net的dll主要是思路基本上是找到第三方的dll的絕對路徑,通過路徑調用
System.Runtime.InteropServices.DllImportAttribute(string dllName)
System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute()
這類方法去調用非.net的dll文件的指定方法。這主要還是看寫組件開發者的寫法,像system.data.sqlite的開發者還提供dll配置方式。可以在初始化時加入配置。然后執行的效果和上面一樣。
但如果沒有配置的是不是一定要把dll放在根目錄上呢。這個問題是關於程序域(AppDomain)的問題還是下一回慢慢解說吧。
版本2的代碼附件https://files.cnblogs.com/files/DasonKwok/MyPlatformV2.zip