/// <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) { if (!ShouldRewrite(method)) return; var declaringType = method.DeclaringType; var body = IL.GetBody(); body.InitLocals = true; var module = declaringType.Module; // Interfaces and Enums cannot be modified if (declaringType.IsInterface || declaringType.IsEnum) return; ImportReferences(module); AddLocals(method); if (!_modifiedTypes.Contains(declaringType)) { AddAdditionalMembers(declaringType); _modifiedTypes.Add(declaringType); } RewriteMethodBody(method, IL, oldInstructions); }
/// <summary> /// Saves the ref arguments of a given method using the /// <paramref name="arguments"/> from the <paramref name="invocationInfo"/> /// object. /// </summary> /// <param name="IL">The <see cref="CilWorker"/> that will emit the method body.</param> /// <param name="parameters">The parameters of the target method.</param> /// <param name="invocationInfo">The local variable that contains the <see cref="IInvocationInfo"/> instance.</param> /// <param name="arguments">The local variable that will store the arguments from the <see cref="IInvocationInfo"/> instance.</param> private static void SaveRefArguments(CilWorker IL, IEnumerable<ParameterDefinition> parameters, VariableDefinition invocationInfo, VariableDefinition arguments) { var body = IL.GetBody(); var targetMethod = body.Method; var declaringType = targetMethod.DeclaringType; var module = declaringType.Module; // Save the arguments returned from the handler method var getArguments = module.ImportMethod<IInvocationInfo>("get_Arguments"); IL.Emit(OpCodes.Ldloc, invocationInfo); IL.Emit(OpCodes.Callvirt, getArguments); IL.Emit(OpCodes.Stloc, arguments); var index = 0; foreach (var param in parameters) { if (!param.IsByRef()) { index++; continue; } // Load the destination address IL.Emit(OpCodes.Ldarg, index + 1); // Load the argument value IL.Emit(OpCodes.Ldloc, arguments); IL.Emit(OpCodes.Ldc_I4, index++); IL.Emit(OpCodes.Ldelem_Ref); // Determine the actual parameter type var referenceType = param.ParameterType as ReferenceType; if (referenceType == null) continue; var actualParameterType = referenceType.ElementType; IL.Emit(OpCodes.Unbox_Any, actualParameterType); IL.Stind(param.ParameterType); } }
/// <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) { var body = IL.GetBody(); var declaringType = body.Method.DeclaringType; var module = declaringType.Module; // throw new NotImplementedException(); var notImplementedConstructor = module.ImportConstructor<NotImplementedException>(); IL.Emit(OpCodes.Newobj, notImplementedConstructor); IL.Emit(OpCodes.Throw); }
/// <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); }