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 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 EmitNewObject(MethodDefinition hostMethod, CilWorker IL, MethodReference targetConstructor, TypeReference concreteType) { ParameterDefinitionCollection parameters = targetConstructor.Parameters; Instruction skipInterception = IL.Create(OpCodes.Nop); SaveConstructorArguments(IL, parameters); EmitCreateMethodActivationContext(hostMethod, IL, concreteType); // Skip the interception if an activator cannot be found EmitGetActivator(hostMethod, IL, skipInterception); IL.Emit(OpCodes.Stloc, _currentActivator); IL.Emit(OpCodes.Ldloc, _currentActivator); IL.Emit(OpCodes.Brfalse, skipInterception); // Determine if the activator can instantiate the method from the // current context IL.Emit(OpCodes.Ldloc, _currentActivator); IL.Emit(OpCodes.Ldloc, _methodContext); IL.Emit(OpCodes.Callvirt, _canActivate); IL.Emit(OpCodes.Brfalse, skipInterception); // Use the activator to create the object instance EmitCreateInstance(IL); // } Instruction endCreate = IL.Create(OpCodes.Nop); IL.Emit(OpCodes.Br, endCreate); // else { IL.Append(skipInterception); // Restore the arguments that were popped off the stack // by the list of constructor arguments int parameterCount = parameters.Count; for (int index = 0; index < parameterCount; index++) { ParameterDefinition currentParameter = parameters[index]; IL.Emit(OpCodes.Ldloc, _constructorArguments); IL.Emit(OpCodes.Ldc_I4, index); IL.Emit(OpCodes.Callvirt, _getItem); IL.Emit(OpCodes.Unbox_Any, currentParameter.ParameterType); } IL.Emit(OpCodes.Newobj, targetConstructor); // } IL.Append(endCreate); }
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 AddEpilog(CilWorker IL) { var skipEpilog = IL.Create(OpCodes.Nop); // if (!IsInterceptionDisabled && surroundingImplementation != null) { IL.Emit(OpCodes.Ldloc, _interceptionDisabled); IL.Emit(OpCodes.Brtrue, skipEpilog); // surroundingImplementation.AfterInvoke(invocationInfo, returnValue); var emitAfterInvoke = new EmitAfterInvoke(_surroundingImplementation, _surroundingClassImplementation, _invocationInfo, _returnValue); emitAfterInvoke.Emit(IL); // } IL.Append(skipEpilog); }
/// <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 Emit(CilWorker IL) { var method = _hostMethod; var declaringType = method.DeclaringType; var module = declaringType.Module; if (!method.HasThis) { IL.Emit(OpCodes.Ldnull); IL.Emit(OpCodes.Stloc, _methodReplacementProvider); return; } var getProvider = _resolveGetProviderMethod(module); IL.Emit(OpCodes.Ldarg_0); IL.Emit(OpCodes.Callvirt, getProvider); IL.Emit(OpCodes.Stloc, _methodReplacementProvider); }
/// <summary> /// Emits the instructions that obtain the <see cref="IMethodReplacementProvider"/> instance. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> instance.</param> public void Emit(CilWorker IL) { MethodDefinition method = _hostMethod; TypeDefinition declaringType = method.DeclaringType; ModuleDefinition module = declaringType.Module; if (!method.HasThis) { IL.Emit(OpCodes.Ldnull); IL.Emit(OpCodes.Stloc, _methodReplacementProvider); return; } MethodReference getProvider = _resolveGetProviderMethod(module); IL.Emit(OpCodes.Ldarg_0); IL.Emit(OpCodes.Callvirt, getProvider); IL.Emit(OpCodes.Stloc, _methodReplacementProvider); }
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> /// 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); }
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); }
private static void Emit(CilWorker IL, ModuleDefinition module, VariableDefinition surroundingImplementation, VariableDefinition invocationInfo, VariableDefinition returnValue) { Instruction skipInvoke = IL.Create(OpCodes.Nop); Instruction skipPrint = IL.Create(OpCodes.Nop); IL.Emit(OpCodes.Ldloc, surroundingImplementation); IL.Emit(OpCodes.Brtrue, skipPrint); IL.Append(skipPrint); IL.Emit(OpCodes.Ldloc, surroundingImplementation); IL.Emit(OpCodes.Brfalse, skipInvoke); MethodReference aroundInvoke = module.ImportMethod<IAfterInvoke>("AfterInvoke"); IL.Emit(OpCodes.Ldloc, surroundingImplementation); IL.Emit(OpCodes.Ldloc, invocationInfo); IL.Emit(OpCodes.Ldloc, returnValue); IL.Emit(OpCodes.Callvirt, aroundInvoke); IL.Append(skipInvoke); }
private static void GetMethodReplacementInstance(MethodDefinition method, CilWorker IL, VariableDefinition methodReplacement, VariableDefinition methodReplacementProvider, VariableDefinition invocationInfo) { var declaringType = method.DeclaringType; var module = declaringType.Module; var pushInstance = method.HasThis ? IL.Create(OpCodes.Ldarg_0) : IL.Create(OpCodes.Ldnull); var getReplacement = module.ImportMethod<IMethodReplacementProvider>("GetMethodReplacement"); IL.Emit(OpCodes.Ldloc, methodReplacementProvider); var skipGetMethodReplacement = IL.Create(OpCodes.Nop); IL.Emit(OpCodes.Brfalse, skipGetMethodReplacement); IL.Emit(OpCodes.Ldloc, methodReplacementProvider); IL.Append(pushInstance); IL.Emit(OpCodes.Ldloc, invocationInfo); IL.Emit(OpCodes.Callvirt, getReplacement); IL.Emit(OpCodes.Stloc, methodReplacement); IL.Append(skipGetMethodReplacement); }
private void ReconstructMethodArguments(CilWorker IL, MethodReference targetMethod) { if (targetMethod.HasThis) IL.Emit(OpCodes.Ldloc, _target); // Push the arguments back onto the stack foreach (ParameterReference param in targetMethod.Parameters) { IL.Emit(OpCodes.Ldloc, _currentArguments); IL.Emit(OpCodes.Callvirt, _popMethod); IL.Emit(OpCodes.Unbox_Any, param.ParameterType); } }
private void GetInstanceProvider(CilWorker IL) { var skipInstanceProvider = IL.Create(OpCodes.Nop); IL.Emit(OpCodes.Ldarg_0); IL.Emit(OpCodes.Isinst, _hostInterfaceType); IL.Emit(OpCodes.Brfalse, skipInstanceProvider); IL.Emit(OpCodes.Ldarg_0); IL.Emit(OpCodes.Isinst, _hostInterfaceType); IL.Emit(OpCodes.Callvirt, _getProvider); IL.Emit(OpCodes.Stloc, _instanceProvider); IL.Emit(OpCodes.Ldloc, _instanceProvider); IL.Emit(OpCodes.Brtrue, skipInstanceProvider); IL.Append(skipInstanceProvider); }
private void EmitInterceptorCall(CilWorker IL) { // var result = replacement.Intercept(info); IL.Emit(OpCodes.Ldloc, _replacement); IL.Emit(OpCodes.Ldloc, _invocationInfo); IL.Emit(OpCodes.Callvirt, _intercept); }
private void EmitGetMethodReplacement(CilWorker IL, IMethodSignature hostMethod, VariableDefinition provider) { // var replacement = MethodReplacementProvider.GetReplacement(info); IL.Emit(OpCodes.Ldloc, provider); // Push the host instance var pushInstance = hostMethod.HasThis ? IL.Create(OpCodes.Ldarg_0) : IL.Create(OpCodes.Ldnull); IL.Append(pushInstance); IL.Emit(OpCodes.Ldloc, _invocationInfo); IL.Emit(OpCodes.Callvirt, _getReplacement); IL.Emit(OpCodes.Stloc, _replacement); }
private void EmitCanReplace(CilWorker IL, IMethodSignature hostMethod, VariableDefinition provider) { var skipGetProvider = IL.Create(OpCodes.Nop); IL.Emit(OpCodes.Ldloc, provider); IL.Emit(OpCodes.Brfalse, skipGetProvider); IL.Emit(OpCodes.Ldloc, provider); // Push the host instance var pushInstance = hostMethod.HasThis ? IL.Create(OpCodes.Ldarg_0) : IL.Create(OpCodes.Ldnull); IL.Append(pushInstance); IL.Emit(OpCodes.Ldloc, _invocationInfo); IL.Emit(OpCodes.Callvirt, _canReplace); IL.Emit(OpCodes.Stloc, _canReplaceFlag); IL.Append(skipGetProvider); }
private void SaveConstructorArgument(CilWorker IL, ParameterDefinition param) { // Box the type if necessary var parameterType = param.ParameterType; if (parameterType.IsValueType || parameterType is GenericParameter) IL.Emit(OpCodes.Box, parameterType); // Save the current argument IL.Emit(OpCodes.Stloc, _currentArgument); // Add the item to the item to the collection IL.Emit(OpCodes.Ldloc, _constructorArguments); IL.Emit(OpCodes.Ldloc, _currentArgument); IL.Emit(OpCodes.Callvirt, _addMethod); }
private void EmitGetActivator(MethodDefinition method, CilWorker IL, Instruction skipInterception) { IL.Emit(OpCodes.Ldloc, _methodContext); IL.Emit(OpCodes.Call, _getStaticActivator); }
private void EmitCreateMethodActivationContext(MethodDefinition method, CilWorker IL, TypeReference concreteType) { // TODO: Add static method support var pushThis = method.IsStatic ? IL.Create(OpCodes.Ldnull) : IL.Create(OpCodes.Ldarg_0); // Push the 'this' pointer onto the stack IL.Append(pushThis); var module = method.DeclaringType.Module; // Push the current method onto the stack IL.PushMethod(method, module); // Push the concrete type onto the stack IL.Emit(OpCodes.Ldtoken, concreteType); IL.Emit(OpCodes.Call, _getTypeFromHandle); IL.Emit(OpCodes.Ldloc, _constructorArguments); IL.Emit(OpCodes.Callvirt, _toArrayMethod); IL.Emit(OpCodes.Newobj, _methodActivationContextCtor); // var context = new MethodActivationContext(this, currentMethod, concreteType, args); IL.Emit(OpCodes.Stloc, _methodContext); }
/// <summary> /// Rewrites a target method using the given CilWorker. /// </summary> /// <param name="method">The target method.</param> /// <param name="IL">The CilWorker that will be used to rewrite the target method.</param> /// <param name="oldInstructions">The original instructions from the target method body.</param> 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); }
private void Replace(CilWorker IL, Instruction oldInstruction, MethodReference targetMethod, MethodDefinition hostMethod, Instruction endLabel, Instruction callOriginalMethod) { var returnType = targetMethod.ReturnType.ReturnType; var module = hostMethod.DeclaringType.Module; if (!hostMethod.IsStatic) GetInstanceProvider(IL); var pushInstance = hostMethod.HasThis ? IL.Create(OpCodes.Ldarg_0) : IL.Create(OpCodes.Ldnull); // If all else fails, use the static method replacement provider IL.Append(pushInstance); IL.Emit(OpCodes.Ldloc, _invocationInfo); IL.Emit(OpCodes.Call, _getStaticProvider); IL.Emit(OpCodes.Stloc, _staticProvider); var restoreArgumentStack = IL.Create(OpCodes.Nop); var callReplacement = IL.Create(OpCodes.Nop); var useStaticProvider = IL.Create(OpCodes.Nop); #region Use the instance method replacement provider IL.Emit(OpCodes.Ldloc, _instanceProvider); IL.Emit(OpCodes.Brfalse, useStaticProvider); EmitCanReplace(IL, hostMethod, _instanceProvider); IL.Emit(OpCodes.Ldloc, _canReplaceFlag); IL.Emit(OpCodes.Brfalse, useStaticProvider); EmitGetMethodReplacement(IL, hostMethod, _instanceProvider); IL.Emit(OpCodes.Ldloc, _replacement); IL.Emit(OpCodes.Brtrue, callReplacement); #endregion IL.Append(useStaticProvider); // if (!MethodReplacementProvider.CanReplace(info)) // CallOriginalMethod(); EmitCanReplace(IL, hostMethod, _staticProvider); IL.Emit(OpCodes.Ldloc, _canReplaceFlag); IL.Emit(OpCodes.Brfalse, restoreArgumentStack); EmitGetMethodReplacement(IL, hostMethod, _staticProvider); IL.Append(callReplacement); // if (replacement == null) // CallOriginalMethod(); IL.Emit(OpCodes.Ldloc, _replacement); IL.Emit(OpCodes.Brfalse, restoreArgumentStack); EmitInterceptorCall(IL); IL.PackageReturnValue(module, returnType); IL.Emit(OpCodes.Br, endLabel); IL.Append(restoreArgumentStack); // Reconstruct the method arguments if the interceptor // cannot be found // Push the target instance ReconstructMethodArguments(IL, targetMethod); // Mark the CallOriginalMethod instruction label IL.Append(callOriginalMethod); // Call the original method IL.Append(oldInstruction); }
private void SaveInvocationInfo(CilWorker IL, MethodReference targetMethod, ModuleDefinition module, TypeReference returnType) { // If the target method is an instance method, then the remaining item on the stack // will be the target object instance // Put all the method arguments into the argument stack foreach (ParameterReference param in targetMethod.Parameters) { // Save the current argument var parameterType = param.ParameterType; if (parameterType.IsValueType || parameterType is GenericParameter) IL.Emit(OpCodes.Box, parameterType); IL.Emit(OpCodes.Stloc, _currentArgument); IL.Emit(OpCodes.Ldloc, _currentArguments); IL.Emit(OpCodes.Ldloc, _currentArgument); IL.Emit(OpCodes.Callvirt, _pushMethod); } // Static methods will always have a null reference as the target if (!targetMethod.HasThis) IL.Emit(OpCodes.Ldnull); // Box the target, if necessary var declaringType = targetMethod.GetDeclaringType(); if (targetMethod.HasThis && (declaringType.IsValueType || declaringType is GenericParameter)) IL.Emit(OpCodes.Box, declaringType); // Save the target IL.Emit(OpCodes.Stloc, _target); IL.Emit(OpCodes.Ldloc, _target); // Push the current method IL.PushMethod(targetMethod, module); // Push the stack trace PushStackTrace(IL, module); var systemType = module.Import(typeof(Type)); // Save the parameter types var parameterCount = targetMethod.Parameters.Count; IL.Emit(OpCodes.Ldc_I4, parameterCount); IL.Emit(OpCodes.Newarr, systemType); IL.Emit(OpCodes.Stloc, _parameterTypes); IL.SaveParameterTypes(targetMethod, module, _parameterTypes); IL.Emit(OpCodes.Ldloc, _parameterTypes); // Save the type arguments var genericParameterCount = targetMethod.GenericParameters.Count; IL.Emit(OpCodes.Ldc_I4, genericParameterCount); IL.Emit(OpCodes.Newarr, systemType); IL.Emit(OpCodes.Stloc, _typeArguments); IL.PushGenericArguments(targetMethod, module, _typeArguments); IL.Emit(OpCodes.Ldloc, _typeArguments); // Push the return type IL.PushType(returnType, module); // Save the method arguments IL.Emit(OpCodes.Ldloc, _currentArguments); IL.Emit(OpCodes.Callvirt, _toArray); IL.Emit(OpCodes.Newobj, _invocationInfoCtor); IL.Emit(OpCodes.Stloc, _invocationInfo); }
private void SaveConstructorArguments(CilWorker IL, ParameterDefinitionCollection parameters) { var parameterCount = parameters.Count; IL.Emit(OpCodes.Newobj, _objectListCtor); IL.Emit(OpCodes.Stloc, _constructorArguments); var index = parameterCount - 1; while (index >= 0) { var param = parameters[index]; SaveConstructorArgument(IL, param); index--; } // Reverse the constructor arguments so that they appear in the correct order IL.Emit(OpCodes.Ldloc, _constructorArguments); IL.Emit(OpCodes.Callvirt, _reverseMethod); }
private void EmitCreateInstance(CilWorker IL) { // T instance = this.Activator.CreateInstance(context); IL.Emit(OpCodes.Ldloc, _currentActivator); IL.Emit(OpCodes.Ldloc, _methodContext); IL.Emit(OpCodes.Callvirt, _createInstance); }
protected override void Replace(Instruction oldInstruction, MethodDefinition hostMethod, CilWorker IL) { var targetMethod = (MethodReference)oldInstruction.Operand; var callOriginalMethod = IL.Create(OpCodes.Nop); var returnType = targetMethod.ReturnType.ReturnType; var endLabel = IL.Create(OpCodes.Nop); var module = hostMethod.DeclaringType.Module; // Create the stack that will hold the method arguments IL.Emit(OpCodes.Newobj, _stackCtor); IL.Emit(OpCodes.Stloc, _currentArguments); SaveInvocationInfo(IL, targetMethod, module, returnType); var getInterceptionDisabled = new GetInterceptionDisabled(hostMethod, _interceptionDisabled); getInterceptionDisabled.Emit(IL); var surroundMethodBody = new SurroundMethodBody(_methodReplacementProvider, _aroundInvokeProvider, _invocationInfo, _interceptionDisabled, _returnValue, typeof(AroundInvokeMethodCallRegistry)); surroundMethodBody.AddProlog(IL); // Use the MethodReplacementProvider attached to the // current host instance Replace(IL, oldInstruction, targetMethod, hostMethod, endLabel, callOriginalMethod); IL.Append(endLabel); surroundMethodBody.AddEpilog(IL); }