public void Transform(IAssemblyTracker tracker) { ArgumentUtility.CheckNotNull("tracker", tracker); _tracker = tracker; var mixinTargetTypes = from assemblyDefinition in tracker.GetAssemblies() from typeDefinition in assemblyDefinition.LoadAllTypes() where _checker.CanBeMixed(assemblyDefinition.Name.BuildReflectionAssemblyQualifiedName(typeDefinition)) select new { Assembly = assemblyDefinition, TypeDef = typeDefinition }; foreach (var mixinTargetType in mixinTargetTypes.ToList()) { GenerateNewObjectMethods(mixinTargetType.Assembly, mixinTargetType.TypeDef); } foreach (var assembly in tracker.GetAssemblies()) { foreach (var typ in assembly.LoadAllTypes()) { ReplaceNewStatement(assembly, typ); } } }
public bool ReplaceNewStatements(AssemblyDefinition containingAssembly, TypeDefinition containingType, MethodDefinition targetMethod, IAssemblyTracker tracker) { var isModified = false; if (targetMethod.HasBody) { var instructions = targetMethod.Body.Instructions; VariableDefinition paramListLocal = null; for (int i = 0; i < instructions.Count; i++) { if (instructions[i].OpCode == OpCodes.Newobj) { var constructor = (MethodReference)instructions[i].Operand; var assemblyQualifiedName = containingAssembly.Name.BuildReflectionAssemblyQualifiedName(constructor.DeclaringType); if (!constructor.Parameters.Any(p => p.ParameterType == containingType.Module.TypeSystem.IntPtr) && _checker.IsCached(assemblyQualifiedName) && _checker.CanBeMixed(assemblyQualifiedName)) { targetMethod.Body.SimplifyMacros(); isModified = true; var objectFactory = _referenceGenerator.GetCallableObjectFactoryCreateMethod(containingAssembly, containingType.Module, constructor.DeclaringType, tracker); var paramListCreateReference = _referenceGenerator.GetCallableParamListCreateMethod(containingAssembly, constructor, tracker); if (paramListLocal == null) { targetMethod.Body.InitLocals = true; paramListLocal = new VariableDefinition("__paramList", paramListCreateReference.ReturnType); targetMethod.Body.Variables.Add(paramListLocal); } #region ILsample // 1: ldstr "Test" // 2: newObj // 3: next // ::---- becomes ->> // 1: ldstr "Test" // 2: nop (original call statement - kept as branch target) // 3: call ParamList.Create<string> (string) // 4: stloc tempPList // 5: ldtrue // 6: ldloc tempPList // 7: ldc.i4.0 // 8: newarr object // 9: call ObjectFactory // 10: next #endregion instructions[i].OpCode = OpCodes.Nop; var objectFactoryInstructions = GetObjectFactoryCreateInstructions( objectFactory, containingType, paramListCreateReference, paramListLocal); for (int j = 0; j < objectFactoryInstructions.Length; ++j) { instructions.Insert(i + 1 + j, objectFactoryInstructions[j]); } targetMethod.Body.OptimizeMacros(); } } } } return(isModified); }