緊接上文,繼續對C#熱更新的研究。上文中,已經說了如何基於appDomain來實現對DLL的加載和卸載,進一步,能夠在unity工程中,將Dll打包成資源,經過Assembly.Load的方式加載DLL來實現更新。那麼爲何IOS中就不能這樣操做了呢?
這兩篇文章,對整個IOS不能熱更新的原因,有詳細的講解,對於Mono的JIT編譯模式和AOT編譯模式也有講解。總結來講,就是因爲IOS的Full AOT編譯模式,不容許在IOS系統中動態生成代碼(代碼是能夠在IOS中動態生成的,只是IOS爲了安全性的考慮,禁止了內存的操做權限),因此JIT這種編譯模式被Mono本身就禁止了(IOS下)。
既然不能JIT的編譯,那麼咱們就不能基於Assembly.Load來加載DLL的bytes了。如何解決這個問題?讓咱們看看ILRuntime的解決思路。
2、ILRuntime基於IL虛擬機實現對DLL的熱更新
ILRuntime藉助Mono.Cecil庫來讀取DLL的PE信息,以及當中類型的全部信息,最終獲得方法的IL彙編碼,而後經過內置的IL解譯執行虛擬機來執行DLL中的代碼
一、藉助Mono.Ceil庫來讀取DLL的PE信息以及當中類型的全部信息
首先,是構建一個全局的appDomain(這兒不是程序域的意思,只是取其名字意思來表示)
基於WWW的方式加載AssetBundle或者DLL/PDB後,接下來是將其封入到MemoryStream中,將dll和pdb的bytes都存入到內存流中後,執行其內部實現的LoadAssembly方法。
關鍵的是第一行,從Mono中加載模塊:html
其中ImageReader最終來自BinaryReader:
那麼接下來的ReadImage操做:安全
這四個操做,是最核心的操做,分別讀取DLL的PE的各個信息,這樣咱們就進入下一個步驟。
主要讀取PE的相關信息,不作過多解釋,能夠參看源碼閱讀理解;
讀取分塊數據
封裝一個Section,而後去執行讀取,而後賦值給section的Data,注意回退了Index
4) ReadMetadataapp
核心是兩個操做,一個是ReadMetadataStream,就是根據不一樣的標識符來新建不一樣的存儲結構;一個是ReadTableHeap:函數
初始化heap中的Table後,進行一次Compute,獲取size:編碼
基於這四步操做,咱們能夠將IL的彙編碼存儲到Image中,而後進一步執行後續的CreateModule操做:
其中的ReadModule爲:
具體的讀取manifest和Module內部數據,能夠參看源碼。
讀取完module後,咱們下一篇文章再詳細講解如何執行IL語句,這篇文章先寫到這兒吧 :D