Represents an instruction emitter that saves the return value from a given method call.
Inheritance: IInstructionEmitter
Exemplo n.º 1
0
        /// <summary>
        ///     Adds method body interception to the target method.
        /// </summary>
        /// <param name="IL">The <see cref="ILProcessor" /> pointing to the target method body.</param>
        public void Emit(ILProcessor IL)
        {
            var method     = IL.Body.Method;
            var returnType = method.ReturnType;

            var endLabel = IL.Create(OpCodes.Nop);
            var executeOriginalInstructions = IL.Create(OpCodes.Nop);

            // Execute the method body replacement if and only if
            // interception is enabled
            IL.Emit(OpCodes.Ldloc, _interceptionDisabled);
            IL.Emit(OpCodes.Brtrue, executeOriginalInstructions);

            var invokeReplacement = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Ldloc, _methodReplacementProvider);
            IL.Emit(OpCodes.Brtrue, invokeReplacement);

            IL.Emit(OpCodes.Ldloc, _classMethodReplacementProvider);
            IL.Emit(OpCodes.Brtrue, invokeReplacement);

            IL.Emit(OpCodes.Br, executeOriginalInstructions);
            IL.Append(invokeReplacement);

            // This is equivalent to the following code:
            // var replacement = provider.GetMethodReplacement(info);
            var invokeMethodReplacement = new InvokeMethodReplacement(executeOriginalInstructions,
                                                                      _methodReplacementProvider,
                                                                      _classMethodReplacementProvider, _invocationInfo);

            invokeMethodReplacement.Emit(IL);

            IL.Emit(OpCodes.Br, endLabel);


            IL.Append(executeOriginalInstructions);
            var addOriginalInstructions = new AddOriginalInstructions(_oldInstructions, endLabel);

            addOriginalInstructions.Emit(IL);


            // Mark the end of the method body
            IL.Append(endLabel);

            var saveReturnValue = new SaveReturnValue(returnType, _returnValue);

            saveReturnValue.Emit(IL);
        }
        public void Emit(CilWorker IL)
        {
            var method = IL.GetMethod();
            var returnType = method.ReturnType.ReturnType;

            var endLabel = IL.Create(OpCodes.Nop);
            var executeOriginalInstructions = IL.Create(OpCodes.Nop);

            // Execute the method body replacement if and only if
            // interception is enabled
            IL.Emit(OpCodes.Ldloc, _interceptionDisabled);
            IL.Emit(OpCodes.Brtrue, executeOriginalInstructions);

            var invokeReplacement = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Ldloc, _methodReplacementProvider);
            IL.Emit(OpCodes.Brtrue, invokeReplacement);

            IL.Emit(OpCodes.Ldloc, _classMethodReplacementProvider);
            IL.Emit(OpCodes.Brtrue, invokeReplacement);

            IL.Emit(OpCodes.Br, executeOriginalInstructions);
            IL.Append(invokeReplacement);

            // This is equivalent to the following code:
            // var replacement = provider.GetMethodReplacement(info);
            var invokeMethodReplacement = new InvokeMethodReplacement(executeOriginalInstructions,
                _methodReplacementProvider, _classMethodReplacementProvider, _invocationInfo);
            invokeMethodReplacement.Emit(IL);

            IL.Emit(OpCodes.Br, endLabel);

            #region The original instruction block
            IL.Append(executeOriginalInstructions);
            var addOriginalInstructions = new AddOriginalInstructions(_oldInstructions, endLabel);
            addOriginalInstructions.Emit(IL);

            #endregion

            // Mark the end of the method body
            IL.Append(endLabel);

            var saveReturnValue = new SaveReturnValue(returnType, _returnValue);
            saveReturnValue.Emit(IL);
        }