12.Unity-MonoCecil 方法重定向 初探

Cecil是一個(gè)用來(lái)生成和檢查“ECMA CIL”格式的程序和類庫(kù)的一個(gè)類庫(kù)。用來(lái)對(duì)IL層的代碼注入,達(dá)到代碼重定向的作用。
通過(guò)了解MonoCecil,了解IL碼寫(xiě)法,了解IL熱更框架的原理
對(duì)于Unity方法重定向,還是更加推薦其他開(kāi)源項(xiàng)目:
比如MonoHook,UnityHook,DotNetHook等等,找一個(gè)合適就可以。
使用MonoCecil實(shí)現(xiàn)方法重定向
將Test() 重定向?yàn)?Test2()
使用監(jiān)視器的按鈕執(zhí)行Test函數(shù)

注入前的輸出結(jié)果

注入后執(zhí)行Test方法, 方法已經(jīng)重定向到Test2()


下面展示如何實(shí)現(xiàn)
環(huán)境需要: Mono.Cecil.dll、Mono.Cecil.Mdb.dll、Mono.Cecil.Pdb.dl
這里直接借用ILRuntime的

XiaoCaoTest類需要放在AssemblyDef的環(huán)境中

注入邏輯
在編輯器中執(zhí)行一次DoInject()
首先獲取必要數(shù)據(jù):AssemblyDefinition,TypeDefinition
獲取完數(shù)據(jù)->執(zhí)行注入InjectMethod
1.獲取方法1(MethodDefinition)->獲取方法1的IL指令
2.在指令前插入新指令: InsertBefore
????輸入?yún)?shù)->無(wú)參數(shù)->自身 ->? OpCodes.Ldarg_0?
????調(diào)用方法2 OpCodes.Call , method2
????return中斷 -> OpCodes.Ret
其他函數(shù)
獲取AssemblyDef
dll文件一般放在項(xiàng)目的 Library\ScriptAssemblies中
計(jì)算注入后的函數(shù)偏移值
必要Using補(bǔ)充
缺點(diǎn):是在dll文件中注入,當(dāng)編輯器重新編譯時(shí),dll中注入的內(nèi)容會(huì)消失。需要重新注入。
而自動(dòng)注入的方法也過(guò)于麻煩。
自動(dòng)注入的思路:
使用[InitializeOnLoadMethod]標(biāo)記配合
CompilationPipeline.assemblyCompilationFinished += CallBack
注冊(cè)編譯完成的回調(diào),執(zhí)行注入。
但還要注意,一個(gè)dll只能注入一次,注入多次,注入的結(jié)果會(huì)累加在dll中。
所以就需要一個(gè)變量來(lái)緩存是否已經(jīng)注入過(guò)。可以在目標(biāo)類加入一個(gè)標(biāo)記用的方法,如果方法存在則說(shuō)明注入過(guò),不需要注入。
這類自動(dòng)注入,在其他熱更框架上應(yīng)該都做得很好。