.net載入失敗的程式集重新載入
在.net程式中,程式集是Lazy載入的,只有在用的時候才會去載入,當程式集載入失敗時,會觸發AppDomain.AssemblyResolve的事件,在這個事件中,我們甚至還可以進行補救,從別得地方重新載入程式集。
AppDomain.CurrentDomain.AssemblyResolve += (s, e) =>
{
byte[] content = getLibBytes(e.Name);
return Assembly.Load(content);
};
這個功能如果使用起來就非常靈活了,它可以控制我們自由控制程式集的載入方式。常用的方法有如下幾個:
程式集保護:
.net程式是非常容易反編譯的,這個特性提供了混淆外的另一個方式。由於動態呼叫的方式下,程式集不需要是原始dll,甚至都不需要儲存在磁碟上。可以通過直接不讓使用者獲取到程式集的dll的方式防止反編譯。
釋出的程式的時候,不直接釋出需要保護的程式集,將程式集加密後釋出,或者直接加密後儲存在伺服器上。使用的時候,在AssemblyResolve中獲取加密後的程式集,解密後返回。
程式集合並:
WPF程式由於使用了反射,使用傳統的ILMerge的方式合併後,由於程式集變化了,往往不能正常工作。
有很多工具,通過將程式集合併到exe的資原始檔中,使用的時候,再在ssemblyResolve中從資原始檔中獲取程式集返回。具體可以參看我之前的文章: 使用LibZ合併.Net程式集
客戶端更新:
CS模式的程式一個不足就是更新不方便,可以將程式集儲存在檔案資料庫中,直接更新程式集資料庫就可以很方便的實現程式集更新。
程式集儲存分離:
使用微服務模式時,很多部署在同一個伺服器上的服務共用著相同的程式集(第三方的Nuget庫),這些程式集更新頻率很低,並且混在一起儲存使得我們不容易找到業務程式集。
可以將這些程式集集中儲存在獨立的位置。服務資料夾中只發布我們的業務程式集,看起來更加清晰,更新也更加方便。
.net core
在.net core中,這個機制也是可以使用的,不過介面發生了一點變化:
AssemblyLoadContext.Default.Resolving += (context, assembly) =>
{
var content = getLibBytes(assembly.FullName);
return Assembly.Load(content);
};
需要說明的是,如果是使用 dotnet xxx.dll 的方式執行的話,dotnet 程式會首先通過 xxx.deps.json檔案來獲取所有相關的依賴性,從而還沒有進入程式就報錯。
可以通過修改 xxx.deps.json去掉依賴項,或者乾脆直接刪掉xxx.deps.json解決這個問題。