示例#1
0
        /*********
        ** Private methods
        *********/
        /// <summary>Rewrite a loaded type definition.</summary>
        /// <param name="type">The type definition to rewrite.</param>
        /// <returns>Returns whether the type was modified.</returns>
        private bool RewriteTypeDefinition(TypeDefinition type)
        {
            bool changed = false;

            changed |= this.RewriteCustomAttributes(type.CustomAttributes);
            changed |= this.RewriteGenericParameters(type.GenericParameters);

            foreach (InterfaceImplementation @interface in type.Interfaces)
            {
                changed |= this.RewriteTypeReference(@interface.InterfaceType, newType => @interface.InterfaceType = newType);
            }

            if (type.BaseType.FullName != "System.Object")
            {
                changed |= this.RewriteTypeReference(type.BaseType, newType => type.BaseType = newType);
            }

            foreach (MethodDefinition method in type.Methods)
            {
                changed |= this.RewriteTypeReference(method.ReturnType, newType => method.ReturnType = newType);
                changed |= this.RewriteGenericParameters(method.GenericParameters);
                changed |= this.RewriteCustomAttributes(method.CustomAttributes);

                foreach (ParameterDefinition parameter in method.Parameters)
                {
                    changed |= this.RewriteTypeReference(parameter.ParameterType, newType => parameter.ParameterType = newType);
                }

                foreach (var methodOverride in method.Overrides)
                {
                    changed |= this.RewriteMethodReference(methodOverride);
                }

                if (method.HasBody)
                {
                    foreach (VariableDefinition variable in method.Body.Variables)
                    {
                        changed |= this.RewriteTypeReference(variable.VariableType, newType => variable.VariableType = newType);
                    }

                    // rewrite CIL instructions
                    ILProcessor cil = method.Body.GetILProcessor();
                    Collection <Instruction> instructions = cil.Body.Instructions;
                    bool addedInstructions = false;
                    for (int i = 0; i < instructions.Count; i++)
                    {
                        var instruction = instructions[i];
                        if (instruction.OpCode.Code == Code.Nop)
                        {
                            continue;
                        }

                        int oldCount = cil.Body.Instructions.Count;
                        changed |= this.RewriteInstruction(instruction, cil, newInstruction =>
                        {
                            changed = true;
                            cil.Replace(instruction, newInstruction);
                            instruction = newInstruction;
                        });

                        if (cil.Body.Instructions.Count > oldCount)
                        {
                            addedInstructions = true;
                        }
                    }

                    // special case: added instructions may cause an instruction to be out of range
                    // of a short jump that references it
                    if (addedInstructions)
                    {
                        foreach (var instruction in instructions)
                        {
                            var longJumpCode = RewriteHelper.GetEquivalentLongJumpCode(instruction.OpCode);
                            if (longJumpCode != null)
                            {
                                instruction.OpCode = longJumpCode.Value;
                            }
                        }
                        changed = true;
                    }
                }
            }

            return(changed);
        }
示例#2
0
 /// <summary>Get whether a type has a method whose signature matches the one expected by a method reference.</summary>
 /// <param name="type">The type to check.</param>
 /// <param name="reference">The method reference.</param>
 public static bool HasMatchingSignature(Type type, MethodReference reference)
 {
     return(type
            .GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly | BindingFlags.Public)
            .Any(method => RewriteHelper.HasMatchingSignature(method, reference)));
 }
示例#3
0
        /// <summary>Get whether the field is a reference to the expected type and field.</summary>
        /// <param name="instruction">The IL instruction.</param>
        /// <param name="fullTypeName">The full type name containing the expected field.</param>
        /// <param name="fieldName">The name of the expected field.</param>
        public static bool IsFieldReferenceTo(Instruction instruction, string fullTypeName, string fieldName)
        {
            FieldReference fieldRef = RewriteHelper.AsFieldReference(instruction);

            return(RewriteHelper.IsFieldReferenceTo(fieldRef, fullTypeName, fieldName));
        }
示例#4
0
        /// <summary>Rewrite custom attributes if needed.</summary>
        /// <param name="attributes">The current custom attributes.</param>
        private bool RewriteCustomAttributes(Collection <CustomAttribute> attributes)
        {
            bool rewritten = false;

            for (int attrIndex = 0; attrIndex < attributes.Count; attrIndex++)
            {
                CustomAttribute attribute  = attributes[attrIndex];
                bool            curChanged = false;

                // attribute type
                TypeReference newAttrType = null;
                rewritten |= this.RewriteTypeReference(attribute.AttributeType, newType =>
                {
                    newAttrType = newType;
                    curChanged  = true;
                });

                // constructor arguments
                TypeReference[] argTypes = new TypeReference[attribute.ConstructorArguments.Count];
                for (int i = 0; i < argTypes.Length; i++)
                {
                    var arg = attribute.ConstructorArguments[i];

                    argTypes[i] = arg.Type;
                    rewritten  |= this.RewriteTypeReference(arg.Type, newType =>
                    {
                        argTypes[i] = newType;
                        curChanged  = true;
                    });
                }

                // swap attribute
                if (curChanged)
                {
                    // get constructor
                    MethodDefinition constructor = (newAttrType ?? attribute.AttributeType)
                                                   .Resolve()
                                                   .Methods
                                                   .Where(method => method.IsConstructor)
                                                   .FirstOrDefault(ctor => RewriteHelper.HasMatchingSignature(ctor, attribute.Constructor));
                    if (constructor == null)
                    {
                        throw new InvalidOperationException($"Can't rewrite attribute type '{attribute.AttributeType.FullName}' to '{newAttrType?.FullName}', no equivalent constructor found.");
                    }

                    // create new attribute
                    var newAttr = new CustomAttribute(this.Module.ImportReference(constructor));
                    for (int i = 0; i < argTypes.Length; i++)
                    {
                        newAttr.ConstructorArguments.Add(new CustomAttributeArgument(argTypes[i], attribute.ConstructorArguments[i].Value));
                    }
                    foreach (var prop in attribute.Properties)
                    {
                        newAttr.Properties.Add(new CustomAttributeNamedArgument(prop.Name, prop.Argument));
                    }
                    foreach (var field in attribute.Fields)
                    {
                        newAttr.Fields.Add(new CustomAttributeNamedArgument(field.Name, field.Argument));
                    }

                    // swap attribute
                    attributes[attrIndex] = newAttr;
                    rewritten             = true;
                }
            }

            return(rewritten);
        }