Ejemplo n.º 1
0
        private void WrapMethod(ModuleDefinition md, TypeDefinition type, MethodDefinition method, MethodReference getInstanceMethod)
        {
            Logger.LogMessage("\tWeaving Method " + method.Name);

            var methodKeyVariable = new VariableDefinition(md.ImportReference(typeof(string)));

            method.Body.Variables.Add(methodKeyVariable);

            var delegateVariable = new VariableDefinition(md.ImportReference(typeof(Delegate)));

            method.Body.Variables.Add(delegateVariable);

            var boolVariable = new VariableDefinition(md.ImportReference(typeof(bool)));

            method.Body.Variables.Add(boolVariable);

            var         instructions             = method.Body.Instructions;
            var         ilprocessor              = method.Body.GetILProcessor();
            Instruction loadInstructionForReturn = null;

            if (method.ReturnType.FullName != "System.Void" && instructions.Count > 1)
            {
                var secondLastInstruction = instructions.ElementAt(instructions.Count - 2);

                if (secondLastInstruction.IsLoadInstruction())
                {
                    loadInstructionForReturn = secondLastInstruction;
                }
            }

            var retInstruction = instructions.Last();

            List <Instruction> constructorInitialCode = new List <Instruction>();

            if (method.IsConstructor)
            {
                foreach (var i in method.Body.Instructions)
                {
                    if (i.OpCode != OpCodes.Call)
                    {
                        constructorInitialCode.Add(i);
                    }
                    else
                    {
                        constructorInitialCode.Add(i);
                        break;
                    }
                }
            }

            var oldInstruction = method.Body.Instructions.Where(x => x != retInstruction &&
                                                                x != loadInstructionForReturn &&
                                                                !constructorInitialCode.Contains(x)).ToList();

            var lastInstruction = retInstruction;

            method.Body.Instructions.Clear();

            if (loadInstructionForReturn != null)
            {
                method.Body.Instructions.Add(loadInstructionForReturn);
                lastInstruction = loadInstructionForReturn;
            }

            method.Body.Instructions.Add(retInstruction);

            foreach (var instruction in oldInstruction)
            {
                ilprocessor.InsertBefore(lastInstruction, instruction);
            }

            method.Body.InitLocals = true;
            var firstInstruction = method.Body.Instructions.First();

            var parameters = method.Parameters.ToArray();

            var composer = new InstructionComposer(md);

            if (method.IsStatic)
            {
                ComposeStaticMethodInstructions(type, method, delegateVariable, boolVariable, methodKeyVariable, firstInstruction, parameters, composer);
            }
            else
            {
                ComposeInstanceMethodInstructions(type, method, delegateVariable, boolVariable, methodKeyVariable, firstInstruction, parameters, composer, getInstanceMethod, md);
            }

            if (method.ReturnType.FullName == "System.Void")
            {
                composer.Pop();
            }
            else if (method.ReturnType.IsValueType)
            {
                composer.Unbox_Any(method.ReturnType);
            }
            else
            {
                composer.Cast(method.ReturnType);
            }

            if (loadInstructionForReturn != null)
            {
                Instruction storeInstructionForReturn = loadInstructionForReturn.GetStoreInstruction();
                composer.Append(storeInstructionForReturn);
            }

            composer.MoveTo(lastInstruction);

            foreach (var instruction in composer.Instructions)
            {
                ilprocessor.InsertBefore(firstInstruction, instruction);
            }

            foreach (var instruction in constructorInitialCode)
            {
                ilprocessor.InsertBefore(composer.Instructions[0], instruction);
            }
        }
        private static void WrapMethod(ModuleDefinition md, TypeDefinition type, MethodDefinition method, MethodDefinition getInstanceMethod)
        {
            var delegateVariable = new VariableDefinition(md.ImportReference(typeof(Delegate)));

            method.Body.Variables.Add(delegateVariable);

            var boolVariable = new VariableDefinition(md.ImportReference(typeof(bool)));

            method.Body.Variables.Add(boolVariable);

            var         instructions             = method.Body.Instructions;
            var         ilprocessor              = method.Body.GetILProcessor();
            Instruction loadInstructionForReturn = null;

            if (method.ReturnType.FullName != "System.Void" && instructions.Count > 1)
            {
                var secondLastInstruction = instructions.ElementAt(instructions.Count - 2);

                if (IsLoadInstruction(secondLastInstruction))
                {
                    loadInstructionForReturn = secondLastInstruction;
                }
            }

            var retInstruction = instructions.Last();

            var oldInstruction = method.Body.Instructions.Where(x => x != retInstruction &&
                                                                x != loadInstructionForReturn).ToList();

            var lastInstruction = retInstruction;

            method.Body.Instructions.Clear();

            if (loadInstructionForReturn != null)
            {
                method.Body.Instructions.Add(loadInstructionForReturn);
                lastInstruction = loadInstructionForReturn;
            }

            method.Body.Instructions.Add(retInstruction);

            foreach (var instruction in oldInstruction)
            {
                ilprocessor.InsertBefore(lastInstruction, instruction);
            }
            method.Body.InitLocals = true;
            var firstInstruction = method.Body.Instructions.First();

            var parameters = method.Parameters.ToArray();

            var composer = new InstructionComposer(md);

            if (method.IsStatic)
            {
                ComposeStaticMethodInstructions(type, method, delegateVariable, boolVariable, firstInstruction, parameters, composer);
            }
            else
            {
                ComposeInstanceMethodInstructions(type, method, delegateVariable, boolVariable, firstInstruction, parameters, composer, getInstanceMethod);
            }

            if (method.ReturnType.FullName == "System.Void")
            {
                composer.Pop();
            }
            else if (method.ReturnType.IsValueType)
            {
                composer.Unbox_Any(method.ReturnType);
            }
            else
            {
                composer.Cast(method.ReturnType);
            }

            if (loadInstructionForReturn != null)
            {
                Instruction storeInstructionForReturn = GetStoreInstruction(loadInstructionForReturn);
                composer.Append(storeInstructionForReturn);
            }

            composer.MoveTo(lastInstruction);

            foreach (var instruction in composer.Instructions)
            {
                ilprocessor.InsertBefore(firstInstruction, instruction);
            }
        }