protected override void Replace(Instruction oldInstruction, MethodDefinition hostMethod, CilWorker IL) { var targetMethod = (MethodReference)oldInstruction.Operand; var callOriginalMethod = IL.Create(OpCodes.Nop); var returnType = targetMethod.ReturnType.ReturnType; var endLabel = IL.Create(OpCodes.Nop); var module = hostMethod.DeclaringType.Module; // Create the stack that will hold the method arguments IL.Emit(OpCodes.Newobj, _stackCtor); IL.Emit(OpCodes.Stloc, _currentArguments); SaveInvocationInfo(IL, targetMethod, module, returnType); var getInterceptionDisabled = new GetInterceptionDisabled(hostMethod, _interceptionDisabled); getInterceptionDisabled.Emit(IL); var surroundMethodBody = new SurroundMethodBody(_methodReplacementProvider, _aroundInvokeProvider, _invocationInfo, _interceptionDisabled, _returnValue, typeof(AroundInvokeMethodCallRegistry)); surroundMethodBody.AddProlog(IL); // Use the MethodReplacementProvider attached to the // current host instance Replace(IL, oldInstruction, targetMethod, hostMethod, endLabel, callOriginalMethod); IL.Append(endLabel); surroundMethodBody.AddEpilog(IL); }
/// <summary> /// Rewrites the instructions in the target method body. /// </summary> /// <param name="method">The target method.</param> /// <param name="IL">The <see cref="CilWorker"/> instance that represents the method body.</param> /// <param name="oldInstructions">The IL instructions of the original method body.</param> protected override void RewriteMethodBody(MethodDefinition method, CilWorker IL, IEnumerable <Instruction> oldInstructions) { if (IsExcluded(method)) { AddOriginalInstructions(IL, oldInstructions); return; } VariableDefinition interceptionDisabled = method.AddLocal <bool>(); VariableDefinition invocationInfo = method.AddLocal <IInvocationInfo>(); VariableDefinition aroundInvokeProvider = method.AddLocal <IAroundInvokeProvider>(); VariableDefinition methodReplacementProvider = method.AddLocal <IMethodReplacementProvider>(); VariableDefinition returnValue = method.AddLocal <object>(); VariableDefinition classMethodReplacementProvider = method.AddLocal <IMethodReplacementProvider>(); Func <ModuleDefinition, MethodReference> getInstanceMethodReplacementProviderMethod = module => module.Import(typeof(IMethodReplacementHost).GetMethod("get_MethodBodyReplacementProvider")); var parameters = new MethodBodyRewriterParameters(IL, oldInstructions, interceptionDisabled, invocationInfo, returnValue, methodReplacementProvider, aroundInvokeProvider, classMethodReplacementProvider, getInstanceMethodReplacementProviderMethod, typeof(AroundMethodBodyRegistry)); var emitter = new InvocationInfoEmitter(true); IInstructionEmitter getMethodReplacementProvider = new GetMethodReplacementProvider(methodReplacementProvider, method, getInstanceMethodReplacementProviderMethod); IInstructionEmitter getInterceptionDisabled = new GetInterceptionDisabled(parameters); ISurroundMethodBody surroundMethodBody = new SurroundMethodBody(parameters, "AroundMethodBodyProvider"); IInstructionEmitter getClassMethodReplacementProvider = new GetClassMethodReplacementProvider(parameters, module => module.Import( typeof( MethodBodyReplacementProviderRegistry ). GetMethod ("GetProvider"))); IInstructionEmitter addMethodReplacement = new AddMethodReplacementImplementation(parameters); var rewriter = new InterceptAndSurroundMethodBody(emitter, getInterceptionDisabled, surroundMethodBody, getMethodReplacementProvider, getClassMethodReplacementProvider, addMethodReplacement, parameters); // Determine whether or not the method should be intercepted rewriter.Rewrite(method, IL, oldInstructions); }
/// <summary> /// Rewrites the instructions in the target method body. /// </summary> /// <param name="method">The target method.</param> /// <param name="IL">The <see cref="CilWorker"/> instance that represents the method body.</param> /// <param name="oldInstructions">The IL instructions of the original method body.</param> protected override void RewriteMethodBody(MethodDefinition method, CilWorker IL, IEnumerable<Instruction> oldInstructions) { if (IsExcluded(method)) { AddOriginalInstructions(IL, oldInstructions); return; } VariableDefinition interceptionDisabled = method.AddLocal<bool>(); VariableDefinition invocationInfo = method.AddLocal<IInvocationInfo>(); VariableDefinition aroundInvokeProvider = method.AddLocal<IAroundInvokeProvider>(); VariableDefinition methodReplacementProvider = method.AddLocal<IMethodReplacementProvider>(); VariableDefinition returnValue = method.AddLocal<object>(); VariableDefinition classMethodReplacementProvider = method.AddLocal<IMethodReplacementProvider>(); Func<ModuleDefinition, MethodReference> getInstanceMethodReplacementProviderMethod = module => module.Import(typeof (IMethodReplacementHost).GetMethod("get_MethodBodyReplacementProvider")); var parameters = new MethodBodyRewriterParameters(IL, oldInstructions, interceptionDisabled, invocationInfo, returnValue, aroundInvokeProvider, methodReplacementProvider, classMethodReplacementProvider, getInstanceMethodReplacementProviderMethod, typeof (AroundMethodBodyRegistry)); var emitter = new InvocationInfoEmitter(true); IInstructionEmitter getMethodReplacementProvider = new GetMethodReplacementProvider(methodReplacementProvider, method, getInstanceMethodReplacementProviderMethod); IInstructionEmitter getInterceptionDisabled = new GetInterceptionDisabled(parameters); ISurroundMethodBody surroundMethodBody = new SurroundMethodBody(parameters, "AroundMethodBodyProvider"); IInstructionEmitter getClassMethodReplacementProvider = new GetClassMethodReplacementProvider(parameters, module => module.Import( typeof ( MethodBodyReplacementProviderRegistry ). GetMethod ("GetProvider"))); IInstructionEmitter addMethodReplacement = new AddMethodReplacementImplementation(parameters); var rewriter = new InterceptAndSurroundMethodBody(emitter, getInterceptionDisabled, surroundMethodBody, getMethodReplacementProvider, getClassMethodReplacementProvider, addMethodReplacement, parameters); // Determine whether or not the method should be intercepted rewriter.Rewrite(method, IL, oldInstructions); }