private static void ProcessModule(ModuleDefinition module, Func <TypeDefinition, bool> typeFilter = null, Func <MethodDefinition, bool> methodFilter = null) { logger.Info($"Processing Module '{module.Name}'"); var refs = new ModuleReferences(module); // ------------------------------------------------------ logger.Info($"Processing Module '{module.Name}'"); var types = module.Types.Where(x => !x.IsEnum); if (typeFilter != null) { types = types.Where(typeFilter); } foreach (var type in types) { logger.Info($"Processing Type '{type.Name}'"); var loggerField = AddStaticLoggerField(type, refs); IEnumerable <MethodDefinition> methods = type.Methods; if (methodFilter != null) { methods = methods.Where(methodFilter); } foreach (var method in methods) { ProcessMethod(refs, method, loggerField); } } }
private static void ProcessMethod(ModuleReferences refs, MethodDefinition method, FieldDefinition loggerField) { logger.Info($"Processing Method '{method.Name}'"); if (method.Body == null) { return; } int shift = AddCatchLogger(refs, method, loggerField); ReplaceShortInstructions(method); }
private static FieldDefinition AddStaticLoggerField(TypeDefinition type, ModuleReferences refs) { var loggerField = new FieldDefinition(DetermineLoggerFieldName(type), FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.InitOnly, refs.Ilogger); type.Fields.Add(loggerField); FieldReference refLoggerField = loggerField; if (type.HasGenericParameters) { var declaringType = new GenericInstanceType(loggerField.DeclaringType); foreach (var parameter in loggerField.DeclaringType.GenericParameters) { declaringType.GenericArguments.Add(parameter); } refLoggerField = new FieldReference(loggerField.Name, loggerField.FieldType, declaringType); } var initr = new[] { Instruction.Create(OpCodes.Call, refs.GetCurrentClassLogger), Instruction.Create(OpCodes.Stsfld, refLoggerField), }; var cctor = type.Methods.SingleOrDefault(x => x.Name == ".cctor"); if (cctor != null) { // If there is already a private constructor var first = cctor.Body.Instructions.FirstOrDefault(); var il = cctor.Body.GetILProcessor(); if (first != null) { il.InjectBefore(first, initr); } else { cctor.Body.Instructions.AddMany(initr); } } else { // If there is NO private constructor var methodAttributes = MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Static; cctor = new MethodDefinition(".cctor", methodAttributes, type.Module.TypeSystem.Void); type.Methods.Add(cctor); cctor.Body.Instructions.AddMany(initr); cctor.Body.Instructions.Add(Instruction.Create(OpCodes.Ret)); } return(loggerField); }
private static int AddCatchLogger(ModuleReferences refs, MethodDefinition method, FieldDefinition loggerField) { var body = method.Body; var catches = body.ExceptionHandlers.Where(x => x.HandlerType == ExceptionHandlerType.Catch); int result = 0; foreach (var exh in catches) { var hstart = exh.HandlerStart; if (exh.CatchType.FullName == typeof(object).FullName) { exh.CatchType = refs.Exception; } var il = body.GetILProcessor(); int slot = 0; if (hstart.OpCode == OpCodes.Pop) { slot = method.Body.Variables.Count(); method.Body.Variables.Add(new VariableDefinition(refs.Exception)); var newhstart = InstructionHelper.CreateStloc(method, slot); il.Replace(hstart, newhstart); hstart = newhstart; exh.TryEnd = newhstart; exh.HandlerStart = newhstart; } else { slot = InstructionHelper.GetSlot(hstart); } var instructions = new[] { Instruction.Create(OpCodes.Ldsfld, loggerField), InstructionHelper.CreateLdloc(method, slot), Instruction.Create(OpCodes.Ldstr, "AUTOLOG EXCEPTION"), #if NLOG_LT_4311 Instruction.Create(OpCodes.Ldc_I4_0), Instruction.Create(OpCodes.Newarr, refs.Object), #endif Instruction.Create(OpCodes.Callvirt, refs.LogError), }; il.Body.MaxStackSize += 10; il.InjectAfter(hstart, instructions); result += instructions.Sum(x => x.GetSize()); } return(result); }