示例#1
0
        /// <summary>
        /// Adds a prolog to the given method body.
        /// </summary>
        /// <param name="IL">The <see cref="CilWorker"/> that points to the given method body.</param>
        public void AddProlog(CilWorker IL)
        {
            MethodDefinition method = IL.GetMethod();

            _surroundingImplementation      = method.AddLocal <IAroundInvoke>();
            _surroundingClassImplementation = method.AddLocal <IAroundInvoke>();

            Instruction      skipProlog     = IL.Create(OpCodes.Nop);
            TypeDefinition   declaringType  = method.DeclaringType;
            ModuleDefinition module         = declaringType.Module;
            TypeReference    modifiableType = module.ImportType <IModifiableType>();

            if (method.HasThis)
            {
                IL.Emit(OpCodes.Ldarg_0);
                IL.Emit(OpCodes.Isinst, modifiableType);
                IL.Emit(OpCodes.Brfalse, skipProlog);
            }

            IL.Emit(OpCodes.Ldloc, _interceptionDisabled);
            IL.Emit(OpCodes.Brtrue, skipProlog);

            // var provider = this.MethodReplacementProvider;

            if (_getMethodReplacementProvider != null)
            {
                _getMethodReplacementProvider.Emit(IL);
            }

            var getAroundInvokeProvider = new GetAroundInvokeProvider(_aroundInvokeProvider, _providerName);

            getAroundInvokeProvider.Emit(IL);

            // if (aroundInvokeProvider != null ) {
            Instruction skipGetSurroundingImplementation     = IL.Create(OpCodes.Nop);
            var         getSurroundingImplementationInstance = new GetSurroundingImplementationInstance(_aroundInvokeProvider,
                                                                                                        _invocationInfo,
                                                                                                        _surroundingImplementation,
                                                                                                        skipGetSurroundingImplementation);

            getSurroundingImplementationInstance.Emit(IL);

            // }

            IL.Append(skipGetSurroundingImplementation);
            var emitBeforeInvoke = new EmitBeforeInvoke(_invocationInfo, _surroundingClassImplementation,
                                                        _surroundingImplementation, _registryType);

            emitBeforeInvoke.Emit(IL);

            IL.Append(skipProlog);
        }
示例#2
0
        public void Rewrite(MethodDefinition method, CilWorker IL,
                            IEnumerable <Instruction> oldInstructions)
        {
            var targetMethod = _parameters.TargetMethod;
            var worker       = targetMethod.GetILGenerator();
            var module       = worker.GetModule();

            _getInterceptionDisabled.Emit(worker);

            // Construct the InvocationInfo instance
            var skipInvocationInfo = worker.Create(OpCodes.Nop);

            worker.Emit(OpCodes.Ldloc, _parameters.InterceptionDisabled);
            worker.Emit(OpCodes.Brtrue, skipInvocationInfo);


            var interceptedMethod = targetMethod;

            _emitter.Emit(targetMethod, interceptedMethod, _parameters.InvocationInfo);


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

            // var provider = this.MethodReplacementProvider;
            //IL.Emit(OpCodes.Ldloc, _interceptionDisabled);
            //IL.Emit(OpCodes.Brtrue, skipGetReplacementProvider);
            _getInstanceMethodReplacementProvider.Emit(IL);
            _surroundMethodBody.AddProlog(worker);
            IL.Append(skipGetReplacementProvider);

            worker.Append(skipInvocationInfo);

            _getClassMethodReplacementProvider.Emit(worker);



            var returnType = targetMethod.ReturnType.ReturnType;

            _addMethodReplacement.Emit(worker);

            // Save the return value
            TypeReference voidType = module.Import(typeof(void));

            _surroundMethodBody.AddEpilog(worker);

            if (returnType != voidType)
            {
                worker.Emit(OpCodes.Ldloc, _parameters.ReturnValue);
            }

            worker.Emit(OpCodes.Ret);
        }