Inheritance: IEmitInvocationInfo
Beispiel #1
0
        /// <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);
        }
Beispiel #2
0
        /// <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);
        }
        /// <summary>
        /// Rewrites the instructions in the target method body to support dynamic exception handling.
        /// </summary>
        /// <param name="targetMethod">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 targetMethod, CilWorker IL,
                                                  IEnumerable <Instruction> oldInstructions)
        {
            var endOfOriginalInstructionBlock = IL.Create(OpCodes.Nop);
            var addOriginalInstructions       = new AddOriginalInstructions(oldInstructions, endOfOriginalInstructionBlock);


            var endLabel   = IL.Create(OpCodes.Nop);
            var tryStart   = IL.Emit(OpCodes.Nop);
            var tryEnd     = IL.Emit(OpCodes.Nop);
            var catchStart = IL.Emit(OpCodes.Nop);
            var catchEnd   = IL.Emit(OpCodes.Nop);

            var module  = IL.GetModule();
            var handler = new ExceptionHandler(ExceptionHandlerType.Catch);
            var body    = targetMethod.Body;

            body.ExceptionHandlers.Add(handler);

            handler.CatchType = module.ImportType <Exception>();

            handler.TryStart = tryStart;
            handler.TryEnd   = tryEnd;

            handler.HandlerStart = catchStart;
            handler.HandlerEnd   = catchEnd;

            var emitter = new InvocationInfoEmitter(true);

            var returnType = targetMethod.ReturnType.ReturnType;

            // try {
            IL.Append(tryStart);
            addOriginalInstructions.Emit(IL);

            IL.Append(endOfOriginalInstructionBlock);
            if (returnType != _voidType && _returnValue != null)
            {
                IL.Emit(OpCodes.Stloc, _returnValue);
            }

            IL.Emit(OpCodes.Leave, endLabel);

            // }
            IL.Append(tryEnd);
            // catch (Exception ex) {
            IL.Append(catchStart);
            IL.Emit(OpCodes.Stloc, _exception);

            SaveExceptionInfo(targetMethod, emitter);
            IL.Emit(OpCodes.Ldloc, _exceptionInfo);

            var getHandlerMethodInfo = typeof(ExceptionHandlerRegistry).GetMethod("GetHandler");
            var getHandlerMethod     = module.Import(getHandlerMethodInfo);

            IL.Emit(OpCodes.Call, getHandlerMethod);
            IL.Emit(OpCodes.Stloc, _exceptionHandler);

            // if (exceptionHandler == null)
            //      throw;
            var doRethrow = IL.Create(OpCodes.Nop);

            IL.Emit(OpCodes.Ldloc, _exceptionHandler);
            IL.Emit(OpCodes.Brfalse, doRethrow);


            // if (handler.CanCatch(exceptionInfo)) {
            var leaveBlock = IL.Create(OpCodes.Nop);
            var canCatch   = module.ImportMethod <IExceptionHandler>("CanCatch");

            IL.Emit(OpCodes.Ldloc, _exceptionHandler);
            IL.Emit(OpCodes.Ldloc, _exceptionInfo);
            IL.Emit(OpCodes.Callvirt, canCatch);
            IL.Emit(OpCodes.Brfalse, doRethrow);

            var catchMethod = module.ImportMethod <IExceptionHandler>("Catch");

            IL.Emit(OpCodes.Ldloc, _exceptionHandler);
            IL.Emit(OpCodes.Ldloc, _exceptionInfo);
            IL.Emit(OpCodes.Callvirt, catchMethod);
            // }


            var getShouldSkipRethrow = module.ImportMethod <IExceptionHandlerInfo>("get_ShouldSkipRethrow");

            IL.Emit(OpCodes.Ldloc, _exceptionInfo);
            IL.Emit(OpCodes.Callvirt, getShouldSkipRethrow);
            IL.Emit(OpCodes.Brfalse, doRethrow);

            IL.Emit(OpCodes.Br, leaveBlock);

            IL.Append(doRethrow);
            IL.Emit(OpCodes.Rethrow);

            IL.Append(leaveBlock);

            IL.Emit(OpCodes.Leave, endLabel);
            IL.Append(catchEnd);
            // }
            IL.Append(endLabel);

            if (returnType != _voidType && _returnValue != null)
            {
                var returnOriginalValue = IL.Create(OpCodes.Nop);
                var getReturnValue      = module.ImportMethod <IExceptionHandlerInfo>("get_ReturnValue");

                IL.Emit(OpCodes.Ldloc, _exceptionInfo);
                IL.Emit(OpCodes.Brfalse, returnOriginalValue);

                IL.Emit(OpCodes.Ldloc, _exceptionInfo);
                IL.Emit(OpCodes.Callvirt, getReturnValue);
                IL.Emit(OpCodes.Stloc, _returnValue);
                IL.Append(returnOriginalValue);

                IL.Emit(OpCodes.Ldloc, _returnValue);
            }

            IL.Emit(OpCodes.Ret);
        }
        /// <summary>
        /// Rewrites the instructions in the target method body to support dynamic exception handling.
        /// </summary>
        /// <param name="targetMethod">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 targetMethod, CilWorker IL,
            IEnumerable<Instruction> oldInstructions)
        {
            var endOfOriginalInstructionBlock = IL.Create(OpCodes.Nop);
            var addOriginalInstructions = new AddOriginalInstructions(oldInstructions, endOfOriginalInstructionBlock);

            var endLabel = IL.Create(OpCodes.Nop);
            var tryStart = IL.Emit(OpCodes.Nop);
            var tryEnd = IL.Emit(OpCodes.Nop);
            var catchStart = IL.Emit(OpCodes.Nop);
            var catchEnd = IL.Emit(OpCodes.Nop);

            var module = IL.GetModule();
            var handler = new ExceptionHandler(ExceptionHandlerType.Catch);
            var body = targetMethod.Body;
            body.ExceptionHandlers.Add(handler);

            handler.CatchType = module.ImportType<Exception>();

            handler.TryStart = tryStart;
            handler.TryEnd = tryEnd;

            handler.HandlerStart = catchStart;
            handler.HandlerEnd = catchEnd;

            var emitter = new InvocationInfoEmitter(true);

            var returnType = targetMethod.ReturnType.ReturnType;

            // try {
            IL.Append(tryStart);
            addOriginalInstructions.Emit(IL);

            IL.Append(endOfOriginalInstructionBlock);
            if (returnType != _voidType && _returnValue != null)
            {
                IL.Emit(OpCodes.Stloc, _returnValue);
            }

            IL.Emit(OpCodes.Leave, endLabel);

            // }
            IL.Append(tryEnd);
            // catch (Exception ex) {
            IL.Append(catchStart);
            IL.Emit(OpCodes.Stloc, _exception);

            SaveExceptionInfo(targetMethod, emitter);
            IL.Emit(OpCodes.Ldloc, _exceptionInfo);

            var getHandlerMethodInfo = typeof (ExceptionHandlerRegistry).GetMethod("GetHandler");
            var getHandlerMethod = module.Import(getHandlerMethodInfo);
            IL.Emit(OpCodes.Call, getHandlerMethod);
            IL.Emit(OpCodes.Stloc, _exceptionHandler);

            // if (exceptionHandler == null)
            //      throw;
            var doRethrow = IL.Create(OpCodes.Nop);
            IL.Emit(OpCodes.Ldloc, _exceptionHandler);
            IL.Emit(OpCodes.Brfalse, doRethrow);

            // if (handler.CanCatch(exceptionInfo)) {
            var leaveBlock = IL.Create(OpCodes.Nop);
            var canCatch = module.ImportMethod<IExceptionHandler>("CanCatch");
            IL.Emit(OpCodes.Ldloc, _exceptionHandler);
            IL.Emit(OpCodes.Ldloc, _exceptionInfo);
            IL.Emit(OpCodes.Callvirt, canCatch);
            IL.Emit(OpCodes.Brfalse, doRethrow);

            var catchMethod = module.ImportMethod<IExceptionHandler>("Catch");
            IL.Emit(OpCodes.Ldloc, _exceptionHandler);
            IL.Emit(OpCodes.Ldloc, _exceptionInfo);
            IL.Emit(OpCodes.Callvirt, catchMethod);
            // }

            var getShouldSkipRethrow = module.ImportMethod<IExceptionHandlerInfo>("get_ShouldSkipRethrow");
            IL.Emit(OpCodes.Ldloc, _exceptionInfo);
            IL.Emit(OpCodes.Callvirt, getShouldSkipRethrow);
            IL.Emit(OpCodes.Brfalse, doRethrow);

            IL.Emit(OpCodes.Br, leaveBlock);

            IL.Append(doRethrow);
            IL.Emit(OpCodes.Rethrow);

            IL.Append(leaveBlock);

            IL.Emit(OpCodes.Leave, endLabel);
            IL.Append(catchEnd);
            // }
            IL.Append(endLabel);

            if (returnType != _voidType && _returnValue != null)
            {
                var returnOriginalValue = IL.Create(OpCodes.Nop);
                var getReturnValue = module.ImportMethod<IExceptionHandlerInfo>("get_ReturnValue");

                IL.Emit(OpCodes.Ldloc, _exceptionInfo);
                IL.Emit(OpCodes.Brfalse, returnOriginalValue);

                IL.Emit(OpCodes.Ldloc, _exceptionInfo);
                IL.Emit(OpCodes.Callvirt, getReturnValue);
                IL.Emit(OpCodes.Stloc, _returnValue);
                IL.Append(returnOriginalValue);

                IL.Emit(OpCodes.Ldloc, _returnValue);
            }

            IL.Emit(OpCodes.Ret);
        }
 /// <summary>
 /// Initializes the class with the default values.
 /// </summary>
 public MethodBodyEmitter()
 {
     InvocationInfoEmitter = new InvocationInfoEmitter();
 }