/// <summary> /// Emits a Console.WriteLine call using the current CilWorker. /// </summary> /// <param name="IL">The target CilWorker.</param> /// <param name="text">The text that will be written to the console.</param> public static void EmitWriteLine(this CilWorker IL, string text) { var body = IL.GetBody(); var method = body.Method; var declaringType = method.DeclaringType; var module = declaringType.Module; var writeLineMethod = typeof(Console).GetMethod("WriteLine", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string) }, null); IL.Emit(OpCodes.Ldstr, text); IL.Emit(OpCodes.Call, module.Import(writeLineMethod)); }
/// <summary> /// Pushes the stack trace of the currently executing method onto the stack. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param> /// <param name="module">The module that contains the host method.</param> public static void PushStackTrace(this CilWorker IL, ModuleDefinition module) { ConstructorInfo stackTraceConstructor = typeof(StackTrace).GetConstructor(new[] { typeof(int), typeof(bool) }); MethodReference stackTraceCtor = module.Import(stackTraceConstructor); OpCode addDebugSymbols = OpCodes.Ldc_I4_0; IL.Emit(OpCodes.Ldc_I4_1); IL.Emit(addDebugSymbols); IL.Emit(OpCodes.Newobj, stackTraceCtor); }
/// <summary> /// Converts the return value of a method into the <paramref name="returnType">target type</paramref>. /// If the target type is void, then the value will simply be popped from the stack. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param> /// <param name="module">The module that contains the host method.</param> /// <param name="returnType">The method return type itself.</param> public static void PackageReturnValue(this CilWorker IL, ModuleDefinition module, TypeReference returnType) { TypeReference voidType = module.ImportType(typeof(void)); if (returnType == voidType) { IL.Emit(OpCodes.Pop); return; } IL.Emit(OpCodes.Unbox_Any, returnType); }
/// <summary> /// Pushes the current <paramref name="field"/> onto the stack. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param> /// <param name="field">The field that represents the <see cref="FieldInfo"/> that will be pushed onto the stack.</param> /// <param name="module">The module that contains the target field.</param> public static void PushField(this CilWorker IL, FieldReference field, ModuleDefinition module) { var getFieldFromHandle = module.ImportMethod <FieldInfo>("GetFieldFromHandle", typeof(RuntimeFieldHandle), typeof(RuntimeTypeHandle)); var declaringType = GetDeclaringType(field.DeclaringType); IL.Emit(OpCodes.Ldtoken, field); IL.Emit(OpCodes.Ldtoken, declaringType); IL.Emit(OpCodes.Call, getFieldFromHandle); }
/// <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); }
/// <summary> /// Causes the <see cref="CilWorker"/> to make the method throw a /// <see cref="NotImplementedException"/> if the method cannot be found. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> responsible for emitting the method body.</param> protected virtual void ImplementNotFound(CilWorker IL) { MethodBody body = IL.GetBody(); TypeDefinition declaringType = body.Method.DeclaringType; ModuleDefinition module = declaringType.Module; // throw new NotImplementedException(); MethodReference notImplementedConstructor = module.ImportConstructor <NotImplementedException>(); IL.Emit(OpCodes.Newobj, notImplementedConstructor); IL.Emit(OpCodes.Throw); }
/// <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); }
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); }
/// <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) { MethodDefinition targetMethod = _parameters.TargetMethod; CilWorker worker = targetMethod.GetILGenerator(); ModuleDefinition module = worker.GetModule(); _getInterceptionDisabled.Emit(worker); // Construct the InvocationInfo instance Instruction skipInvocationInfo = worker.Create(OpCodes.Nop); worker.Emit(OpCodes.Ldloc, _parameters.InterceptionDisabled); worker.Emit(OpCodes.Brtrue, skipInvocationInfo); MethodDefinition interceptedMethod = targetMethod; _emitter.Emit(targetMethod, interceptedMethod, _parameters.InvocationInfo); Instruction 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); TypeReference 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); }
/// <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) { MethodDefinition targetMethod = IL.GetMethod(); TypeDefinition declaringType = targetMethod.DeclaringType; ModuleDefinition module = declaringType.Module; var getSurroundingClassImplementation = new GetSurroundingClassImplementation(_invocationInfo, _surroundingClassImplementation, _registryType.GetMethod( "GetSurroundingImplementation")); // var classAroundInvoke = AroundInvokeRegistry.GetSurroundingImplementation(info); getSurroundingClassImplementation.Emit(IL); // classAroundInvoke.BeforeInvoke(info); Instruction skipInvoke = IL.Create(OpCodes.Nop); IL.Emit(OpCodes.Ldloc, _surroundingClassImplementation); IL.Emit(OpCodes.Brfalse, skipInvoke); MethodReference 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; } Instruction skipInvoke1 = IL.Create(OpCodes.Nop); IL.Emit(OpCodes.Ldloc, _surroundingImplementation); IL.Emit(OpCodes.Brfalse, skipInvoke1); MethodReference 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); // } }
/// <summary> /// Emits a Console.WriteLine call using the current CilWorker. /// </summary> /// <param name="IL">The target CilWorker.</param> /// <param name="text">The text that will be written to the console.</param> public static void EmitWriteLine(this CilWorker IL, string text) { MethodBody body = IL.GetBody(); MethodDefinition method = body.Method; TypeDefinition declaringType = method.DeclaringType; ModuleDefinition module = declaringType.Module; MethodInfo writeLineMethod = typeof(Console).GetMethod("WriteLine", BindingFlags.Public | BindingFlags.Static, null, new[] { typeof(string) }, null); IL.Emit(OpCodes.Ldstr, text); IL.Emit(OpCodes.Call, module.Import(writeLineMethod)); }
private static void Emit(CilWorker IL, ModuleDefinition module, VariableDefinition surroundingImplementation, VariableDefinition invocationInfo, VariableDefinition returnValue) { var skipInvoke = IL.Create(OpCodes.Nop); var 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); var 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); }
/// <summary> /// Emits the instructions that obtain a class-level <see cref="IMethodReplacementProvider"/> instance. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> instance that points to the instructions in the method body.</param> public void Emit(CilWorker IL) { ModuleDefinition module = IL.GetModule(); MethodDefinition method = IL.GetMethod(); MethodReference getProvider = _resolveGetProviderMethod(module); OpCode 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); }
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); } }
/// <summary> /// Saves the current method signature of a method into an array /// of <see cref="System.Type"/> objects. This can be used to determine the /// signature of methods with generic type parameters or methods that have /// parameters that are generic parameters specified by the type itself. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param> /// <param name="method">The target method whose generic type arguments (if any) will be saved into the local variable .</param> /// <param name="module">The module that contains the host method.</param> /// <param name="parameterTypes">The local variable that will store the current method signature.</param> public static void SaveParameterTypes(this CilWorker IL, MethodReference method, ModuleDefinition module, VariableDefinition parameterTypes) { var getTypeFromHandle = module.ImportMethod <Type>("GetTypeFromHandle", BindingFlags.Public | BindingFlags.Static); var parameterCount = method.Parameters.Count; for (var index = 0; index < parameterCount; index++) { var current = method.Parameters[index]; IL.Emit(OpCodes.Ldloc, parameterTypes); IL.Emit(OpCodes.Ldc_I4, index); IL.Emit(OpCodes.Ldtoken, current.ParameterType); IL.Emit(OpCodes.Call, getTypeFromHandle); IL.Emit(OpCodes.Stelem_Ref); } }
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> /// Saves the current <see cref="IExceptionHandlerInfo"/> instance. /// </summary> /// <param name="targetMethod">The target method.</param> /// <param name="emitter">The <see cref="IEmitInvocationInfo"/> instance that will emit the current method context.</param> private void SaveExceptionInfo(MethodDefinition targetMethod, IEmitInvocationInfo emitter) { CilWorker IL = targetMethod.GetILGenerator(); ModuleDefinition module = IL.GetModule(); emitter.Emit(targetMethod, targetMethod, _invocationInfo); IL.Emit(OpCodes.Ldloc, _exception); IL.Emit(OpCodes.Ldloc, _invocationInfo); MethodReference exceptionInfoConstructor = module.ImportConstructor <ExceptionHandlerInfo>( typeof(Exception), typeof(IInvocationInfo)); IL.Emit(OpCodes.Newobj, exceptionInfoConstructor); IL.Emit(OpCodes.Stloc, _exceptionInfo); TypeReference returnType = targetMethod.ReturnType.ReturnType; if (returnType == _voidType || _returnValue == null) { return; } // exceptionInfo.ReturnValue = returnValue; MethodReference setReturnValue = module.ImportMethod <IExceptionHandlerInfo>("set_ReturnValue"); IL.Emit(OpCodes.Ldloc, _exceptionInfo); IL.Emit(OpCodes.Ldloc, _returnValue); IL.Emit(OpCodes.Callvirt, setReturnValue); }
/// <summary> /// Stores the <paramref name="param">current parameter value</paramref> /// into the array of method <paramref name="arguments"/>. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param> /// <param name="arguments">The local variable that will store the method arguments.</param> /// <param name="index">The array index that indicates where the parameter value will be stored in the array of arguments.</param> /// <param name="param">The current argument value being stored.</param> private static void PushParameter(this CilWorker IL, int index, VariableDefinition arguments, ParameterDefinition param) { var parameterType = param.ParameterType; IL.Emit(OpCodes.Ldloc, arguments); IL.Emit(OpCodes.Ldc_I4, index); // Zero out the [out] parameters if (param.IsOut || param.IsByRef()) { IL.Emit(OpCodes.Ldnull); IL.Emit(OpCodes.Stelem_Ref); return; } IL.Emit(OpCodes.Ldarg, param); if (parameterType.IsValueType || parameterType is GenericParameter) { IL.Emit(OpCodes.Box, param.ParameterType); } IL.Emit(OpCodes.Stelem_Ref); }
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); }
/// <summary> /// Creates a property getter method implementation with the /// <paramref name="propertyType"/> as the return type. /// </summary> /// <param name="propertyType">Represents the <see cref="TypeReference">return type</see> for the getter method.</param> /// <param name="getterName">The getter method name.</param> /// <param name="attributes">The method attributes associated with the getter method.</param> /// <param name="backingField">The field that will store the instance that the getter method will retrieve.</param> /// <returns>A <see cref="MethodDefinition"/> representing the getter method itself.</returns> private static MethodDefinition AddPropertyGetter(TypeReference propertyType, string getterName, MethodAttributes attributes, FieldReference backingField) { var getter = new MethodDefinition(getterName, attributes, propertyType) { IsPublic = true, ImplAttributes = (MethodImplAttributes.Managed | MethodImplAttributes.IL) }; CilWorker IL = getter.GetILGenerator(); IL.Emit(OpCodes.Ldarg_0); IL.Emit(OpCodes.Ldfld, backingField); IL.Emit(OpCodes.Ret); return(getter); }
/// <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); }
/// <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) { 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> /// Saves the generic type arguments that were used to construct the method. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param> /// <param name="method">The target method whose generic type arguments (if any) will be saved into the <paramref name="typeArguments">local variable</paramref>.</param> /// <param name="module">The module that contains the host method.</param> /// <param name="typeArguments">The local variable that will store the resulting array of <see cref="Type"/> objects.</param> public static void PushGenericArguments(this CilWorker IL, IGenericParameterProvider method, ModuleDefinition module, VariableDefinition typeArguments) { var getTypeFromHandle = module.ImportMethod <Type>("GetTypeFromHandle", BindingFlags.Public | BindingFlags.Static); var genericParameterCount = method.GenericParameters.Count; var genericParameters = method.GenericParameters; for (var index = 0; index < genericParameterCount; index++) { var current = genericParameters[index]; IL.Emit(OpCodes.Ldloc, typeArguments); IL.Emit(OpCodes.Ldc_I4, index); IL.Emit(OpCodes.Ldtoken, current); IL.Emit(OpCodes.Call, getTypeFromHandle); IL.Emit(OpCodes.Stelem_Ref); } }
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); }
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); }
/// <summary> /// Creates a property setter method implementation with the /// <paramref name="propertyType"/> as the setter parameter. /// </summary> /// <param name="propertyType">Represents the <see cref="TypeReference">parameter type</see> for the setter method.</param> /// <param name="attributes">The method attributes associated with the setter method.</param> /// <param name="backingField">The field that will store the instance for the setter method.</param> /// <param name="setterName">The method name of the setter method.</param> /// <param name="voidType">The <see cref="TypeReference"/> that represents <see cref="Void"/>.</param> /// <returns>A <see cref="MethodDefinition"/> that represents the setter method itself.</returns> private static MethodDefinition AddPropertySetter(TypeReference propertyType, MethodAttributes attributes, FieldReference backingField, string setterName, TypeReference voidType) { var setter = new MethodDefinition(setterName, attributes, voidType) { IsPublic = true, ImplAttributes = (MethodImplAttributes.Managed | MethodImplAttributes.IL) }; setter.Parameters.Add(new ParameterDefinition(propertyType)); CilWorker IL = setter.GetILGenerator(); IL.Emit(OpCodes.Ldarg_0); IL.Emit(OpCodes.Ldarg_1); IL.Emit(OpCodes.Stfld, backingField); IL.Emit(OpCodes.Ret); return(setter); }
/// <summary> /// Pushes the arguments of a method onto the stack. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that will be used to create the instructions.</param> /// <param name="module">The module that contains the host method.</param> /// <param name="method">The target method.</param> /// <param name="arguments">The <see cref="VariableDefinition">local variable</see> that will hold the array of arguments.</param> public static void PushArguments(this CilWorker IL, IMethodSignature method, ModuleDefinition module, VariableDefinition arguments) { var objectType = module.ImportType(typeof(object)); int parameterCount = method.Parameters.Count; IL.Emit(OpCodes.Ldc_I4, parameterCount); IL.Emit(OpCodes.Newarr, objectType); IL.Emit(OpCodes.Stloc, arguments); if (parameterCount == 0) { return; } var index = 0; foreach (ParameterDefinition param in method.Parameters) { IL.PushParameter(index++, arguments, param); } }
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 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); }