public void Inject() { var typeName = Guid.NewGuid().ToString("N"); var methodName = Guid.NewGuid().ToString("N"); AssemblyManager.Manage((assembly) => { var traceAttributeCtor = assembly.MainModule.Import( typeof(TraceAttribute).GetConstructor(Type.EmptyTypes)); var attribute = new CustomAttribute(traceAttributeCtor); var type = AssemblyManager.AddType(assembly, typeName); var method = AssemblyManager.AddMethod(type, methodName); method.CustomAttributes.Add(attribute); var processor = method.Body.GetILProcessor(); processor.Append(Instruction.Create(OpCodes.Ret)); }, (assembly) => { var injector = new TraceAttribute(); var targetMethod = (from type in assembly.MainModule.GetAllTypes() where type.Name == typeName from method in type.Methods where method.Name == methodName select method).First(); Assert.AreEqual(1, targetMethod.Body.Instructions.Count); injector.Inject(targetMethod); var instructions = targetMethod.Body.Instructions; Assert.AreEqual(12, instructions.Count); Assert.AreEqual(OpCodes.Call, instructions[0].OpCode); Assert.AreEqual(OpCodes.Callvirt, instructions[1].OpCode); Assert.AreEqual(OpCodes.Stloc, instructions[2].OpCode); Assert.AreEqual(OpCodes.Ldloc, instructions[3].OpCode); Assert.AreEqual(OpCodes.Ldstr, instructions[4].OpCode); Assert.AreEqual(OpCodes.Call, instructions[5].OpCode); Assert.AreEqual(OpCodes.Call, instructions[6].OpCode); Assert.AreEqual(OpCodes.Ldloc, instructions[7].OpCode); Assert.AreEqual(OpCodes.Ldstr, instructions[8].OpCode); Assert.AreEqual(OpCodes.Call, instructions[9].OpCode); Assert.AreEqual(OpCodes.Call, instructions[10].OpCode); Assert.AreEqual(OpCodes.Ret, instructions[11].OpCode); }, false); }
public void InjectWithThrowOpCode() { var typeName = Guid.NewGuid().ToString("N"); var methodName = Guid.NewGuid().ToString("N"); AssemblyManager.Manage((assembly) => { var traceAttributeCtor = assembly.MainModule.Import( typeof(TraceAttribute).GetConstructor(Type.EmptyTypes)); var attribute = new CustomAttribute(traceAttributeCtor); var type = AssemblyManager.AddType(assembly, typeName); var method = AssemblyManager.AddMethod(type, methodName, new List <ParameterDefinition> { new ParameterDefinition(assembly.MainModule.Import(typeof(bool))) }, null); method.CustomAttributes.Add(attribute); var processor = method.Body.GetILProcessor(); var first = Instruction.Create(OpCodes.Ldarg_0); processor.Append(first); var argumentNullExceptionCtor = assembly.MainModule.Import( typeof(ArgumentNullException).GetConstructor(new Type[] { typeof(string) })); processor.Append(Instruction.Create(OpCodes.Ldstr, "error")); processor.Append(Instruction.Create(OpCodes.Newobj, argumentNullExceptionCtor)); processor.Append(Instruction.Create(OpCodes.Throw)); var last = Instruction.Create(OpCodes.Ret); processor.Append(last); processor.InsertAfter(first, Instruction.Create(OpCodes.Brfalse_S, last)); }, (assembly) => { var injector = new TraceAttribute(); var targetMethod = (from type in assembly.MainModule.GetAllTypes() where type.Name == typeName from method in type.Methods where method.Name == methodName select method).First(); Assert.AreEqual(6, targetMethod.Body.Instructions.Count); injector.Inject(targetMethod); Assert.AreEqual(21, targetMethod.Body.Instructions.Count); var instructions = targetMethod.Body.Instructions; Assert.AreEqual(OpCodes.Call, instructions[0].OpCode); Assert.AreEqual(OpCodes.Callvirt, instructions[1].OpCode); Assert.AreEqual(OpCodes.Stloc, instructions[2].OpCode); Assert.AreEqual(OpCodes.Ldloc, instructions[3].OpCode); Assert.AreEqual(OpCodes.Ldstr, instructions[4].OpCode); Assert.AreEqual(OpCodes.Call, instructions[5].OpCode); Assert.AreEqual(OpCodes.Call, instructions[6].OpCode); Assert.AreEqual(OpCodes.Ldarg_0, instructions[7].OpCode); Assert.AreEqual(OpCodes.Brfalse_S, instructions[8].OpCode); Assert.AreEqual(OpCodes.Ldstr, instructions[9].OpCode); Assert.AreEqual(OpCodes.Newobj, instructions[10].OpCode); Assert.AreEqual(OpCodes.Ldloc, instructions[11].OpCode); Assert.AreEqual(OpCodes.Ldstr, instructions[12].OpCode); Assert.AreEqual(OpCodes.Call, instructions[13].OpCode); Assert.AreEqual(OpCodes.Call, instructions[14].OpCode); Assert.AreEqual(OpCodes.Throw, instructions[15].OpCode); Assert.AreEqual(OpCodes.Ldloc, instructions[16].OpCode); Assert.AreEqual(OpCodes.Ldstr, instructions[17].OpCode); Assert.AreEqual(OpCodes.Call, instructions[18].OpCode); Assert.AreEqual(OpCodes.Call, instructions[19].OpCode); Assert.AreEqual(OpCodes.Ret, instructions[20].OpCode); }, false); }