C# 元件模組引用第三方元件問題
對接上一文章由於是動態載入指定程式集,會把當前目錄下所有 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