public void Emit(CilWorker IL) { var module = IL.GetModule(); var modifiableType = module.ImportType<IModifiableType>(); var getInterceptionDisabledMethod = module.ImportMethod<IModifiableType>("get_IsInterceptionDisabled"); if (!_hostMethod.HasThis) { IL.Emit(OpCodes.Ldc_I4_0); IL.Emit(OpCodes.Stloc, _interceptionDisabled); return; } var skipLabel = IL.Create(OpCodes.Nop); // var interceptionDisabled = this.IsInterceptionDisabled; IL.Emit(OpCodes.Ldarg_0); IL.Emit(OpCodes.Isinst, modifiableType); IL.Emit(OpCodes.Brfalse, skipLabel); IL.Emit(OpCodes.Ldarg_0); IL.Emit(OpCodes.Isinst, modifiableType); IL.Emit(OpCodes.Callvirt, getInterceptionDisabledMethod); IL.Emit(OpCodes.Stloc, _interceptionDisabled); IL.Append(skipLabel); }
/// <summary> /// Emits the call to the <see cref="IAfterInvoke"/> instance. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that points to the current method body.</param> public void Emit(CilWorker IL) { ModuleDefinition module = IL.GetModule(); // instanceAroundInvoke.AfterInvoke(info, returnValue); Emit(IL, module, _surroundingImplementation, _invocationInfo, _returnValue); // classAroundInvoke.AfterInvoke(info, returnValue); Emit(IL, module, _surroundingClassImplementation, _invocationInfo, _returnValue); }
/// <summary> /// Saves the return value from a given method call. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> pointing to the target method body.</param> public void Emit(CilWorker IL) { ModuleDefinition module = IL.GetModule(); TypeReference voidType = module.ImportType(typeof (void)); bool returnTypeIsValueType = _returnType != voidType && _returnType.IsValueType; if (_returnType is GenericParameter || returnTypeIsValueType) IL.Create(OpCodes.Box, _returnType); if (_returnType != voidType) IL.Create(OpCodes.Stloc, _returnValue); }
/// <summary> /// Saves the return value from a given method call. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> pointing to the target method body.</param> public void Emit(CilWorker IL) { var module = IL.GetModule(); var voidType = module.ImportType(typeof (void)); var returnTypeIsValueType = _returnType != voidType && _returnType.IsValueType; if (_returnType is GenericParameter || returnTypeIsValueType) IL.Create(OpCodes.Box, _returnType); if (_returnType != voidType) IL.Create(OpCodes.Stloc, _returnValue); }
public void Emit(CilWorker IL) { var module = IL.GetModule(); var method = IL.GetMethod(); var getProvider = _resolveGetProviderMethod(module); var pushThis = method.HasThis ? OpCodes.Ldarg_0 : OpCodes.Ldnull; IL.Emit(pushThis); IL.Emit(OpCodes.Ldloc, _invocationInfo); IL.Emit(OpCodes.Call, getProvider); IL.Emit(OpCodes.Stloc, _classMethodReplacementProvider); }
public void Emit(CilWorker IL) { var module = IL.GetModule(); IL.Emit(OpCodes.Ldloc, _aroundInvokeProvider); IL.Emit(OpCodes.Brfalse, _skipGetSurroundingImplementation); // var surroundingImplementation = this.GetSurroundingImplementation(this, invocationInfo); var getSurroundingImplementation = module.ImportMethod<IAroundInvokeProvider>("GetSurroundingImplementation"); IL.Emit(OpCodes.Ldloc, _aroundInvokeProvider); IL.Emit(OpCodes.Ldloc, _invocationInfo); IL.Emit(OpCodes.Callvirt, getSurroundingImplementation); IL.Emit(OpCodes.Stloc, _surroundingImplementation); }
public void Emit(CilWorker IL) { var method = IL.GetMethod(); var module = IL.GetModule(); // var aroundInvokeProvider = this.AroundInvokeProvider; var getAroundInvokeProvider = module.ImportMethod<IModifiableType>("get_AroundInvokeProvider"); if (!method.HasThis) { IL.Emit(OpCodes.Ldnull); IL.Emit(OpCodes.Stloc, _aroundInvokeProvider); return; } IL.Emit(OpCodes.Ldarg_0); IL.Emit(OpCodes.Callvirt, getAroundInvokeProvider); IL.Emit(OpCodes.Stloc, _aroundInvokeProvider); }
/// <summary> /// Emits the call to obtain the <see cref="IAroundInvokeProvider"/> instance. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> pointing to the target method body.</param> public void Emit(CilWorker IL) { MethodDefinition method = IL.GetMethod(); ModuleDefinition module = IL.GetModule(); // var aroundInvokeProvider = this.AroundInvokeProvider; string propertyName = string.Format("get_{0}", _providerName); MethodReference getAroundInvokeProvider = module.ImportMethod<IAroundInvokeHost>(propertyName); if (!method.HasThis) { IL.Emit(OpCodes.Ldnull); IL.Emit(OpCodes.Stloc, _aroundInvokeProvider); return; } IL.Emit(OpCodes.Ldarg_0); IL.Emit(OpCodes.Callvirt, getAroundInvokeProvider); IL.Emit(OpCodes.Stloc, _aroundInvokeProvider); }
public void Emit(CilWorker IL) { var module = IL.GetModule(); var method = IL.GetMethod(); var returnType = method.ReturnType.ReturnType; var methodReplacement = MethodDefinitionExtensions.AddLocal(method, typeof(IInterceptor)); GetMethodReplacementInstance(method, IL, methodReplacement, _methodReplacementProvider, _invocationInfo); var skipGetClassMethodReplacement = IL.Create(OpCodes.Nop); IL.Emit(OpCodes.Ldloc, methodReplacement); IL.Emit(OpCodes.Brtrue, skipGetClassMethodReplacement); GetMethodReplacementInstance(method, IL, methodReplacement, _classMethodReplacementProvider, _invocationInfo); IL.Append(skipGetClassMethodReplacement); IL.Emit(OpCodes.Ldloc, methodReplacement); IL.Emit(OpCodes.Brfalse, _executeOriginalInstructions); // var returnValue = replacement.Intercept(info); InvokeInterceptor(module, IL, methodReplacement, returnType, _invocationInfo); }
/// <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); }