/// <summary> /// 注入每个热修方法对应的luaFunction定义 /// </summary> /// <param name="typeDefinition"></param> private static List <FieldDefinition> InjectLuaFunctionDefForType(TypeDefinition typeDefinition) { List <FieldDefinition> bridgeLuaFuncs = new List <FieldDefinition>(); Type type = FindType(typeDefinition.FullName); bool isUnityComponent = type.IsAssignableFrom(typeof(UnityEngine.Component)); foreach (var methodDef in typeDefinition.Methods) { if (!LuaInjectUtil.IsMethodNeedHotFix(methodDef, isUnityComponent)) { continue; } var luaFuncVarName = LuaInjectUtil.GetHotFixFunctionNameInCS(methodDef); FieldDefinition fieldDefinition = new FieldDefinition(luaFuncVarName, FieldAttributes.Private | FieldAttributes.Static, typeRef_LuaFunction); foreach (var field in typeDefinition.Fields) { if (field.Name == luaFuncVarName) { typeDefinition.Fields.Remove(field); break; } } typeDefinition.Fields.Add(fieldDefinition); bridgeLuaFuncs.Add(fieldDefinition); } return(bridgeLuaFuncs); }
public static void InjectToIL() { Debug.Log("InjectTool Inject Start"); if (Application.isPlaying || EditorApplication.isCompiling) { Debug.Log("You need stop play mode or wait compiling finished"); return; } EditorApplication.LockReloadAssemblies(); // 按路径读取程序集 var readerParameters = new ReaderParameters { ReadSymbols = true }; var assembly = AssemblyDefinition.ReadAssembly(AssemblyPath, readerParameters); if (assembly == null) { Debug.LogError(string.Format("InjectTool Inject Load assembly failed: {0}", AssemblyPath)); return; } try { var module = assembly.MainModule; //1.收集类型和方法引用 CollectTypeMethodReference(module); bool skip = false; // 如果已经注入过,则不再注入 if (module.Types.Any(t => t.Name == "__HOTFIX_FLAG")) { Debug.Log("InjectManager InjectHotFixInAssembly Skip"); skip = true; } if (!skip) { // 添加注入标记 module.Types.Add(new TypeDefinition("__HOTFIX", "__HOTFIX_FLAG", TypeAttributes.Class, typeRef_object)); foreach (var type in module.Types) { if (!LuaInjectUtil.IsTypeNeedHotFix(type)) { continue; } Debug.Log(string.Format("InjectTool start inject for type:{0}", type.Name)); //2.添加ObjectLuaHotFixState var hotfixStateField = InjectHotfixStateField(type); //3.注入每个方法对应的LuaFunction声明 var bridgeLuaFuncs = InjectLuaFunctionDefForType(type); //4.注入TryInitHotFix函数 var tryInitHotFixMethod = InjectTryInitHotFixFunc(type, hotfixStateField); //5.注入InitHotFix函数 InjectInitHotFixFunc(type, hotfixStateField, bridgeLuaFuncs); //6.为每个函数注入拦截代码片段 Type realType = FindType(type.FullName); bool isUnityComponent = typeof(UnityEngine.Component).IsAssignableFrom(realType); foreach (var methodDef in type.Methods) { if (!LuaInjectUtil.IsMethodNeedHotFix(methodDef, isUnityComponent)) { continue; } Debug.Log(string.Format("InjectTool start inject for type:{0} method:{1}", type.Name, methodDef.Name)); var bridgeLuaFunc = bridgeLuaFuncs.Find((field) => { return(field.Name == LuaInjectUtil.GetHotFixFunctionNameInCS(methodDef)); }); InjectRedirectCodeForMethod(module, type, methodDef, tryInitHotFixMethod, bridgeLuaFunc); } } } assembly.Write(AssemblyPath, new WriterParameters { WriteSymbols = true }); } catch (Exception ex) { Debug.LogError(string.Format("InjectTool Inject failed: {0}", ex)); throw; } finally { if (assembly.MainModule.SymbolReader != null) { Debug.Log("InjectTool Inject SymbolReader.Dispose Succeed"); assembly.MainModule.SymbolReader.Dispose(); } } EditorApplication.UnlockReloadAssemblies(); Debug.Log("InjectTool Inject End"); }
/// <summary> /// 为类型注入InitHotFix函数 /// </summary> /// <param name="typeDefinition"></param> private static void InjectInitHotFixFunc(TypeDefinition typeDefinition, FieldReference hotfixState, List <FieldDefinition> bridgeLuaFuncs) { string funcName = "InitHotFix"; foreach (var method in typeDefinition.Methods) { if (method.Name == funcName) { typeDefinition.Methods.Remove(method); break; } } MethodDefinition initHotFixMethod = new MethodDefinition(funcName, MethodAttributes.Static | MethodAttributes.Private, typeRef_bool); initHotFixMethod.Body = new Mono.Cecil.Cil.MethodBody(initHotFixMethod); initHotFixMethod.Parameters.Add(new ParameterDefinition("luaModule", ParameterAttributes.None, typeRef_LuaTable)); initHotFixMethod.Body = new Mono.Cecil.Cil.MethodBody(initHotFixMethod); initHotFixMethod.Body.MaxStackSize = 4; initHotFixMethod.Body.Variables.Add(new VariableDefinition(typeRef_bool)); initHotFixMethod.Body.Variables.Add(new VariableDefinition(typeRef_bool)); // 开始注入IL代码 var ilProcessor = initHotFixMethod.Body.GetILProcessor(); initHotFixMethod.Body.Instructions.Add(ilProcessor.Create(OpCodes.Ret)); var insertPoint = initHotFixMethod.Body.Instructions[0]; // 设置一些标签用于语句跳转 var label1 = ilProcessor.Create(OpCodes.Nop); var label2 = ilProcessor.Create(OpCodes.Ldloc_0); var label3 = ilProcessor.Create(OpCodes.Ldloc_1); // if (luaModule == null) ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Nop)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Ldc_I4_0)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Stloc_0)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Ldarg_0)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Ldnull)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Call, methodRef_LuaVar_op_Equality)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Brfalse, label1)); //result = false; 将0压入局部变量索引零处 ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Nop)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Ldc_I4_0)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Stloc_0)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Nop)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Br, label2)); //luaModule != null ilProcessor.InsertBefore(insertPoint, label1); //OpCodes.Nop //初始化方法对应的luaFunction变量 Type type = FindType(typeDefinition.FullName); bool isUnityComponent = type.IsAssignableFrom(typeof(UnityEngine.Component)); foreach (var methodDef in typeDefinition.Methods) { //for example: //m_Add_ThisInt32Int32_fix = (luaModule.get("Add_ThisInt32Int32", rawget: true) as LuaFunction); if (!LuaInjectUtil.IsMethodNeedHotFix(methodDef, isUnityComponent)) { continue; } var bridgeLuaFunc = bridgeLuaFuncs.Find((field) => { return(field.Name == LuaInjectUtil.GetHotFixFunctionNameInCS(methodDef)); }); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Ldarg_0)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Ldstr, LuaInjectUtil.GetHotFixFunctionNameInLua(methodDef))); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Ldc_I4_0)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Ldc_I4_1)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Callvirt, methodRef_LuaTable_get)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Isinst, typeRef_LuaFunction)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Stsfld, bridgeLuaFunc)); } ////result = true; 将1压入局部变量索引零处 ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Ldc_I4_1)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Stloc_0)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Nop)); ilProcessor.InsertBefore(insertPoint, label2);//OpCodes.Ldloc_0 ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Stloc_1)); ilProcessor.InsertBefore(insertPoint, ilProcessor.Create(OpCodes.Br, label3)); ilProcessor.InsertBefore(insertPoint, label3);//OpCodes.Ldloc_1 typeDefinition.Methods.Add(initHotFixMethod); }