Пример #1
0
        static bool injectMethod(AssemblyDefinition assembly, MethodDefinition method, int hotfixType, FieldReference stateTable)
        {
            var type = method.DeclaringType;
            var luaDelegateName = getDelegateName(method);
            if (luaDelegateName == null)
            {
                Debug.LogError("too many overload!");
                return false;
            }

            bool isFinalize = method.Name == "Finalize";

            TypeReference delegateType = null;
            MethodReference invoke = null;

            int param_count = method.Parameters.Count + (method.IsStatic ? 0 : 1);

            if (!findHotfixDelegate(assembly, method, out delegateType, out invoke, hotfixType))
            {
                Debug.LogError("can not find delegate for " + method.DeclaringType + "." + method.Name + "! try re-genertate code.");
                return false;
            }

            if (delegateType == null || invoke == null)
            {
                throw new Exception("unknow exception!");
            }
            FieldDefinition fieldDefinition = new FieldDefinition(luaDelegateName, Mono.Cecil.FieldAttributes.Static | Mono.Cecil.FieldAttributes.Private,
                delegateType);
            type.Fields.Add(fieldDefinition);
            FieldReference fieldReference = fieldDefinition.GetGeneric();

            bool statefulConstructor = (hotfixType == 1) && method.IsConstructor && !method.IsStatic;

            var firstIns = method.Body.Instructions[0];
            var processor = method.Body.GetILProcessor();

            processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldsfld, fieldReference));
            processor.InsertBefore(firstIns, processor.Create(OpCodes.Brfalse, firstIns));

            if (statefulConstructor)
            {
                processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldarg_0));
            }
            processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldsfld, fieldReference));
            for (int i = 0; i < param_count; i++)
            {
                if (i < ldargs.Length)
                {
                    processor.InsertBefore(firstIns, processor.Create(ldargs[i]));
                }
                else
                {
                    processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldarg, (short)i));
                }
                if (i == 0 && hotfixType == 1 && !method.IsStatic && !method.IsConstructor)
                {
                    processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldfld, stateTable));
                }
                else if (i == 0 && !method.IsStatic && type.IsValueType)
                {
                    processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldobj, type));
                }
            }

            processor.InsertBefore(firstIns, processor.Create(OpCodes.Call, invoke));
            if (statefulConstructor)
            {
                processor.InsertBefore(firstIns, processor.Create(OpCodes.Stfld, stateTable));
            }
            if (isFinalize && hotfixType == 1)
            {
                processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldarg_0));
                processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldnull));
                processor.InsertBefore(firstIns, processor.Create(OpCodes.Stfld, stateTable));
            }
            if (!method.IsConstructor && !isFinalize)
            {
                processor.InsertBefore(firstIns, processor.Create(OpCodes.Ret));
            }

            if (isFinalize)
            {
                method.Body.ExceptionHandlers[0].TryStart = method.Body.Instructions[0];
            }

            return true;
        }
Пример #2
0
        static bool injectType(AssemblyDefinition assembly, TypeReference hotfixAttributeType, TypeDefinition type)
        {
            foreach(var nestedTypes in type.NestedTypes)
            {
                if (!injectType(assembly, hotfixAttributeType, nestedTypes))
                {
                    return false;
                }
            }
            CustomAttribute hotfixAttr = type.CustomAttributes.FirstOrDefault(ca => ca.AttributeType == hotfixAttributeType);
            int hotfixType;
            if (hotfixAttr != null)
            {
                hotfixType = (int)hotfixAttr.ConstructorArguments[0].Value;
            }
            else
            {
                if (!hotfixCfg.ContainsKey(type.FullName))
                {
                    return true;
                }
                hotfixType = (int)hotfixCfg[type.FullName];
            }

            FieldReference stateTable = null;
            if (hotfixType == 1)
            {
                if (type.IsAbstract && type.IsSealed)
                {
                    throw new InvalidOperationException(type.FullName + " is static, can not be mark as Stateful!");
                }
                var stateTableDefinition = new FieldDefinition("__Hitfix_xluaStateTable", Mono.Cecil.FieldAttributes.Private, luaTableType);
                type.Fields.Add(stateTableDefinition);
                stateTable = stateTableDefinition.GetGeneric();
            }
            foreach (var method in type.Methods)
            {
                if (method.Name != ".cctor" && !method.IsAbstract && !method.IsPInvokeImpl && method.Body != null)
                {
                    if ((method.HasGenericParameters || genericInOut(assembly, method)) ? !injectGenericMethod(assembly, method, hotfixType, stateTable) :
                        !injectMethod(assembly, method, hotfixType, stateTable))
                    {
                        return false;
                    }
                }
            }
            return true;
        }
Пример #3
0
        static bool injectGenericMethod(AssemblyDefinition assembly, MethodDefinition method, int hotfixType, FieldReference stateTable)
        {
            var type = method.DeclaringType;
            var luaDelegateName = getDelegateName(method);
            if (luaDelegateName == null)
            {
                Debug.LogError("too many overload!");
                return false;
            }

            bool isFinalize = method.Name == "Finalize";

            FieldDefinition fieldDefinition = new FieldDefinition(luaDelegateName, Mono.Cecil.FieldAttributes.Static | Mono.Cecil.FieldAttributes.Private,
                luaFunctionType);
            type.Fields.Add(fieldDefinition);

            FieldReference fieldReference = fieldDefinition.GetGeneric();

            int param_start = method.IsStatic ? 0 : 1;
            int param_count = method.Parameters.Count + param_start;
            var firstIns = method.Body.Instructions[0];
            var processor = method.Body.GetILProcessor();

            processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldsfld, fieldReference));
            processor.InsertBefore(firstIns, processor.Create(OpCodes.Brfalse, firstIns));

            processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldsfld, fieldReference));
            processor.InsertBefore(firstIns, processor.Create(OpCodes.Callvirt, invokeSessionStart));

            bool statefulConstructor = (hotfixType == 1) && method.IsConstructor && !method.IsStatic;

            TypeReference returnType = statefulConstructor ? luaTableType : method.ReturnType;

            bool isVoid = returnType.FullName == "System.Void";

            int outCout = 0;

            for (int i = 0; i < param_count; i++)
            {
                if (i == 0 && !method.IsStatic)
                {
                    processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldsfld, fieldReference));
                    processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldarg_0));
                    if (hotfixType == 1 && !method.IsConstructor)
                    {
                        processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldfld, stateTable));
                        processor.InsertBefore(firstIns, processor.Create(OpCodes.Callvirt, MakeGenericMethod(inParam, luaTableType)));
                    }
                    else
                    {
                        if (type.IsValueType)
                        {
                            processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldobj, method.DeclaringType.GetGeneric()));
                        }
                        processor.InsertBefore(firstIns, processor.Create(OpCodes.Callvirt, MakeGenericMethod(inParam, method.DeclaringType.GetGeneric())));
                    }
                }
                else
                {
                    var param = method.Parameters[i - param_start];
                    if (param.ParameterType.IsByReference)
                    {
                        outCout++;
                    }
                    if (!param.IsOut)
                    {
                        processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldsfld, fieldReference));

                        if (i < ldargs.Length)
                        {
                            processor.InsertBefore(firstIns, processor.Create(ldargs[i]));
                        }
                        else
                        {
                            processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldarg, (short)i));
                        }

                        var paramType = param.ParameterType;

                        if (param.ParameterType.IsByReference)
                        {
                            paramType = ((ByReferenceType)paramType).ElementType;
                            if (paramType.IsValueType || paramType.IsGenericParameter)
                            {
                                processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldobj, paramType));
                            }
                            else
                            {
                                processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldind_Ref));
                            }
                        }
                        if (i == param_count - 1 && param.CustomAttributes.Any(ca => ca.AttributeType.FullName == "System.ParamArrayAttribute"))
                        {
                            processor.InsertBefore(firstIns, processor.Create(OpCodes.Callvirt, MakeGenericMethod(inParams, ((ArrayType)paramType).ElementType)));
                        }
                        else
                        {
                            processor.InsertBefore(firstIns, processor.Create(OpCodes.Callvirt, MakeGenericMethod(inParam, paramType)));
                        }
                    }
                }
            }

            int outStart = (isVoid ? 0 : 1);

            processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldsfld, fieldReference));
            processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldc_I4, outCout + outStart));
            processor.InsertBefore(firstIns, processor.Create(OpCodes.Callvirt, functionInvoke));

            int outPos = outStart;
            for (int i = 0; i < method.Parameters.Count; i++)
            {
                if (method.Parameters[i].ParameterType.IsByReference)
                {
                    processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldsfld, fieldReference));
                    processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldc_I4, outPos));
                    int arg_pos = param_start + i;
                    if (arg_pos < ldargs.Length)
                    {
                        processor.InsertBefore(firstIns, processor.Create(ldargs[arg_pos]));
                    }
                    else
                    {
                        processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldarg, (short)arg_pos));
                    }
                    processor.InsertBefore(firstIns, processor.Create(OpCodes.Callvirt, MakeGenericMethod(outParam,
                        ((ByReferenceType)method.Parameters[i].ParameterType).ElementType)));
                    outPos++;
                }
            }
            if (statefulConstructor)
            {
                processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldarg_0));
            }
            processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldsfld, fieldReference));
            if (isVoid)
            {
                processor.InsertBefore(firstIns, processor.Create(OpCodes.Callvirt, invokeSessionEnd));
            }
            else
            {
                processor.InsertBefore(firstIns, processor.Create(OpCodes.Callvirt, MakeGenericMethod(invokeSessionEndWithResult, returnType)));
            }
            if (statefulConstructor)
            {
                processor.InsertBefore(firstIns, processor.Create(OpCodes.Stfld, stateTable));
            }
            if (isFinalize && hotfixType == 1)
            {
                processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldarg_0));
                processor.InsertBefore(firstIns, processor.Create(OpCodes.Ldnull));
                processor.InsertBefore(firstIns, processor.Create(OpCodes.Stfld, stateTable));
            }
            if (!method.IsConstructor && !isFinalize)
            {
                processor.InsertBefore(firstIns, processor.Create(OpCodes.Ret));
            }

            if (isFinalize)
            {
                method.Body.ExceptionHandlers[0].TryStart = method.Body.Instructions[0];
            }

            return true;
        }