/// <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); }