示例#1
0
        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);
        }