Exemplo n.º 1
0
        /// <summary>Rewrite a CIL instruction if needed.</summary>
        /// <param name="instruction">The current CIL instruction.</param>
        /// <param name="cil">The CIL instruction processor.</param>
        /// <param name="replaceWith">Replaces the CIL instruction with a new one.</param>
        private bool RewriteInstruction(Instruction instruction, ILProcessor cil, Action <Instruction> replaceWith)
        {
            bool rewritten = false;

            // field reference
            FieldReference fieldRef = RewriteHelper.AsFieldReference(instruction);

            if (fieldRef != null)
            {
                rewritten |= this.RewriteTypeReference(fieldRef.DeclaringType, newType => fieldRef.DeclaringType = newType);
                rewritten |= this.RewriteTypeReference(fieldRef.FieldType, newType => fieldRef.FieldType = newType);
            }

            // method reference
            MethodReference methodRef = RewriteHelper.AsMethodReference(instruction);

            if (methodRef != null)
            {
                this.RewriteMethodReference(methodRef);
            }

            // type reference
            if (instruction.Operand is TypeReference typeRef)
            {
                rewritten |= this.RewriteTypeReference(typeRef, newType => replaceWith(cil.Create(instruction.OpCode, newType)));
            }

            // instruction itself
            // (should be done after the above type rewrites to ensure valid types)
            rewritten |= this.RewriteInstructionImpl(ref instruction, cil);

            return(rewritten);
        }
        /*********
        ** Private methods
        *********/
        /// <summary>Rewrite a CIL instruction if needed.</summary>
        /// <param name="instruction">The current CIL instruction.</param>
        /// <param name="cil">The CIL instruction processor.</param>
        /// <param name="replaceWith">Replaces the CIL instruction with a new one.</param>
        private bool RewriteInstruction(Instruction instruction, ILProcessor cil, Action <Instruction> replaceWith)
        {
            bool rewritten = false;

            // field reference
            FieldReference fieldRef = RewriteHelper.AsFieldReference(instruction);

            if (fieldRef != null)
            {
                rewritten |= this.RewriteTypeReference(fieldRef.DeclaringType, newType => fieldRef.DeclaringType = newType);
                rewritten |= this.RewriteTypeReference(fieldRef.FieldType, newType => fieldRef.FieldType = newType);
            }

            // method reference
            MethodReference methodRef = RewriteHelper.AsMethodReference(instruction);

            if (methodRef != null)
            {
                rewritten |= this.RewriteTypeReference(methodRef.DeclaringType, newType =>
                {
                    // note: generic methods are wrapped into a MethodSpecification which doesn't allow changing the
                    // declaring type directly. For our purposes we want to change all generic versions of a matched
                    // method anyway, so we can use GetElementMethod to get the underlying method here.
                    methodRef.GetElementMethod().DeclaringType = newType;
                });
                rewritten |= this.RewriteTypeReference(methodRef.ReturnType, newType => methodRef.ReturnType = newType);

                foreach (var parameter in methodRef.Parameters)
                {
                    rewritten |= this.RewriteTypeReference(parameter.ParameterType, newType => parameter.ParameterType = newType);
                }

                if (methodRef is GenericInstanceMethod genericRef)
                {
                    for (int i = 0; i < genericRef.GenericArguments.Count; i++)
                    {
                        rewritten |= this.RewriteTypeReference(genericRef.GenericArguments[i], newType => genericRef.GenericArguments[i] = newType);
                    }
                }
            }

            // type reference
            if (instruction.Operand is TypeReference typeRef)
            {
                rewritten |= this.RewriteTypeReference(typeRef, newType => replaceWith(cil.Create(instruction.OpCode, newType)));
            }

            // instruction itself
            // (should be done after the above type rewrites to ensure valid types)
            rewritten |= this.RewriteInstructionImpl(instruction, cil, newInstruction =>
            {
                rewritten = true;
                cil.Replace(instruction, newInstruction);
                instruction = newInstruction;
            });

            return(rewritten);
        }