轉載請標明出處:http://www.cnblogs.com/zblade/
最近研究了一下如何在unity中實現c#的熱更新,對於整個DLL熱更新的過程和方案有一個初步的了解,這兒就寫下來,便於后續的深入調查和方案選擇。
一、C# DLL的動態加載和卸載
既然要熱更新,那么就是動態的加載c#的DLL,所以第一步就是研究如何實現DLL的動態加載和卸載。
在CLR Via C#中,對於DLL的加載有詳細的講解,這兒就不再長篇幅的講解整個過程,簡單的來說,在C#的工程中,都會生成一個默認的程序域appDomain,就叫做DefaultAppDomain吧,在這個程序域的基礎上,我們可以加載多個不同的程序集。在.Net中,程序集不能卸載,但是可以隨着程序域的釋放而一起釋放,所以我們可以利用程序域來實現程序集(DLL)的加載和釋放。
上面的理論來自CLR Via C#, 具體的圖為:

基於這個理論,我們可以在DefaultAppDomain之外,再多次創建多個AppDomain,基於AppDomain來實現DLL的加載和卸載。基於此,編寫相關的工程測試,參考網上的一個工程來進一步的測試,這兒是原文,文末有相關的代碼下載:
在原代碼的基礎上,進一步構建。首先,構建4個Class Library:
默認工程為MainServer,將Module1和Module2的Build路徑設置到MainServer的bin中,這樣MainServer就可以加載最新的Module1.DLL/Module2.DLL(PS:這兒的設置很重要,忽略會使得不能加載最新的DLL)
Module1和Module2都在References中添加CommonLib的引用,實現ICalculater接口,各自的實現為:
Module1:

Module2:
這樣,就是兩個不同的Class Library中,分別實現了ICalculater接口,分別為相加和相乘。在MainServer的主程序入口Program中:
首先在默認appDomain的基礎上,進一步加載2個appDomain,然后分別在這2個程序域的基礎上加載DLL。得到的結果為:
整個步驟都詳細的解釋了整個執行流程,先構建appDomain,在此基礎上,加載dll,然后執行里面的方法。再一個新的appDomain中加載前面加載過的dll,再次執行,相互之間並不沖突。所以appDomain可以一對多個DLL,一個DLL可以被多個不同的AppDomain加載。
二、Unity中測試DLL的加載
在第一部分的基礎上,我們進一步的研究如何在Unity中實現Dll的加載,基本的操作步驟可以參考這篇文章:unity dll實現熱更新
當然,文章並不是完全的實現熱更新,實現的是windows和android平台下,對於dll文件的熱更新。對於IOS為什么不能熱更新,我們后續會討論到,先看看安卓和windows下 dll的熱更新步驟。
1、新建一個ClassLibrary(類庫)的工程,在其中實現對應的類和方法;
2、將該工程導出為DLL;
3、將DLL改為bytes文件,存入Unity工程中的StreamingAssets文件夾下;
4、在工程運行的時候,讀取StreamingAssets下的Dll文件,用Assembly.Load(byte[] bytes )的方法,將DLL文件讀取出來,進而執行相關的操作。這一步的代碼為:
對於DLL文件,是執行www.bytes,對於assetbundle文件,則是執行ab.mainAsset轉換為TextAsset,進一步得到bytes。在windows和android平台下,都會得到這樣的屏幕輸出:
這個方案的本質,和前面的本質相差不大,unity工程在執行的時候,會構建一個默認的appDomain,Assembly.Load,其實就是在這個程序域上加載Dll,所以相關的實質和前面一個部分相差不大,這就是c#熱更新在unity中的應用(IOS不包括)。
下文我們會講解IOS為什么不支持DLL的熱更新,以及如何利用ILRuntime來實現Android和IOS的熱更新。