/// <summary> /// Emits the instructions that obtain the <see cref="IAroundInvoke"/> instance. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that points to the current method body.</param> public void Emit(CilWorker IL) { var method = IL.GetMethod(); var declaringType = method.DeclaringType; var module = declaringType.Module; var getSurroundingImplementation = module.Import(_getSurroundingImplementationMethod); IL.Emit(OpCodes.Ldloc, _invocationInfo); IL.Emit(OpCodes.Call, getSurroundingImplementation); IL.Emit(OpCodes.Stloc, _surroundingClassImplementation); }
/// <summary> /// Emits the instructions that obtain the <see cref="IAroundInvoke"/> instance. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that points to the current method body.</param> public void Emit(CilWorker IL) { MethodDefinition method = IL.GetMethod(); TypeDefinition declaringType = method.DeclaringType; ModuleDefinition module = declaringType.Module; MethodReference getSurroundingImplementation = module.Import(_getSurroundingImplementationMethod); IL.Emit(OpCodes.Ldloc, _invocationInfo); IL.Emit(OpCodes.Call, getSurroundingImplementation); IL.Emit(OpCodes.Stloc, _surroundingClassImplementation); }
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); }
/// <summary> /// Adds method body interception to the target method. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> pointing to the target method body.</param> public void Emit(CilWorker IL) { MethodDefinition method = IL.GetMethod(); TypeReference returnType = method.ReturnType.ReturnType; Instruction endLabel = IL.Create(OpCodes.Nop); Instruction 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); Instruction 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); }
/// <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) { var targetMethod = IL.GetMethod(); var declaringType = targetMethod.DeclaringType; var module = declaringType.Module; var getSurroundingClassImplementation = new GetSurroundingClassImplementation(_invocationInfo, _surroundingClassImplementation, _registryType.GetMethod( "GetSurroundingImplementation")); // var classAroundInvoke = AroundInvokeRegistry.GetSurroundingImplementation(info); getSurroundingClassImplementation.Emit(IL); // classAroundInvoke.BeforeInvoke(info); var skipInvoke = IL.Create(OpCodes.Nop); IL.Emit(OpCodes.Ldloc, _surroundingClassImplementation); IL.Emit(OpCodes.Brfalse, skipInvoke); var beforeInvoke = module.ImportMethod<IBeforeInvoke>("BeforeInvoke"); // surroundingImplementation.BeforeInvoke(invocationInfo); IL.Emit(OpCodes.Ldloc, _surroundingClassImplementation); IL.Emit(OpCodes.Ldloc, _invocationInfo); IL.Emit(OpCodes.Callvirt, beforeInvoke); IL.Append(skipInvoke); // if (surroundingImplementation != null) { if (!targetMethod.HasThis) return; var skipInvoke1 = IL.Create(OpCodes.Nop); IL.Emit(OpCodes.Ldloc, _surroundingImplementation); IL.Emit(OpCodes.Brfalse, skipInvoke1); var beforeInvoke1 = module.ImportMethod<IBeforeInvoke>("BeforeInvoke"); // surroundingImplementation.BeforeInvoke(invocationInfo); IL.Emit(OpCodes.Ldloc, _surroundingImplementation); IL.Emit(OpCodes.Ldloc, _invocationInfo); IL.Emit(OpCodes.Callvirt, beforeInvoke1); IL.Append(skipInvoke1); // } }
public void AddProlog(CilWorker IL) { var method = IL.GetMethod(); _surroundingImplementation = method.AddLocal<IAroundInvoke>(); _surroundingClassImplementation = method.AddLocal<IAroundInvoke>(); var skipProlog = IL.Create(OpCodes.Nop); var declaringType = method.DeclaringType; var module = declaringType.Module; var 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); getAroundInvokeProvider.Emit(IL); // if (aroundInvokeProvider != null ) { var 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); }
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); }