コード例 #1
0
        /// <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);
        }
コード例 #2
0
        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");
        }
コード例 #3
0
        /// <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);
        }