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); } }