/// <summary>
        /// Generates a hook that is called before any native code
        /// </summary>
        /// <param name="method">Method to generate the hook in</param>
        /// <param name="options">Configurable hook options</param>
        /// <returns>A <see cref="MergableMethod"/> instance</returns>
        public static MergableMethod GenerateBeginHook
        (
            this MethodDefinition method,

            HookOptions options = HookOptions.Default,
            VariableDefinition result_variable = null
        )
        {
            // emit call at offset 0

            // add or get the types where we are storing out auto generated hooks & their delegates
            var hooks_type           = method.DeclaringType.GetHooksType();
            var hooks_delegates_type = method.DeclaringType.GetHooksDelegateType();

            // generate the hook handler delegate
            var hook_delegate_emitter = new HookDelegateEmitter("OnPre", method, options);
            var hook_handler          = hook_delegate_emitter.Emit();

            hooks_delegates_type.NestedTypes.Add(hook_handler);

            // generate the api hook external modules can attach to
            var hook_field = new FieldDefinition("Pre" + method.GetSafeName(), FieldAttributes.Public | FieldAttributes.Static, hook_handler);

            hooks_type.Fields.Add(hook_field);

            // generate the call to the delegate
            var hook_emitter = new HookEmitter(hook_field, method,
                                               (options & HookOptions.Cancellable) != 0,
                                               (options & HookOptions.ReferenceParameters) != 0,
                                               result_variable
                                               );
            var result = hook_emitter.Emit();
            //instructions.MergeInto(method, 0);

            // end of method

            var invoke_method = hook_handler.Resolve().Method("Invoke");

            if (invoke_method.ReturnType.FullName != "System.Void")
            {
                result.Instructions = result.Instructions.Concat(new[]
                {
                    Instruction.Create(OpCodes.Brtrue_S, method.Body.Instructions.First()),
                    Instruction.Create(OpCodes.Br_S, method.Body.Instructions.Last())
                });
            }

            return(result);
        }
        /// <summary>
        /// Generates a hook that is called after native code
        /// </summary>
        /// <param name="method">Method to generate the hook in</param>
        /// <param name="options">Configurable hook options</param>
        /// <returns>A <see cref="MergableMethod"/> instance</returns>
        public static MergableMethod GenerateHook
        (
            this IEnumerable <ParameterDefinition> parameters,

            string name,
            TypeDefinition parentType,
            TypeDefinition returnType, HookOptions flags, ModuleDefinition module,

            HookOptions options = HookOptions.Post,
            VariableDefinition result_variable = null
        )
        {
            // emit call at each ret instruction

            // add or get the types where we are storing out auto generated hooks & their delegates
            var hooks_type           = parentType.GetHooksType();
            var hooks_delegates_type = parentType.GetHooksDelegateType();

            // generate the hook handler delegate
            var hook_delegate_emitter = new HookDelegateEmitter("On" + name, parameters, returnType, options, module);
            var hook_handler          = hook_delegate_emitter.Emit();

            hooks_delegates_type.NestedTypes.Add(hook_handler);

            // generate the api hook external modules can attach to
            var hook_field = new FieldDefinition(name, FieldAttributes.Public | FieldAttributes.Static, hook_handler);

            hooks_type.Fields.Add(hook_field);

            // generate the call to the delegate
            var hook_emitter = new HookEmitter(hook_field, parameters, false, false, result_variable);
            var result       = hook_emitter.Emit();


            // end of method

            return(result);
        }
        /// <summary>
        /// Generates a hook that is called after native code
        /// </summary>
        /// <param name="method">Method to generate the hook in</param>
        /// <param name="options">Configurable hook options</param>
        /// <returns>A <see cref="MergableMethod"/> instance</returns>
        public static MergableMethod GenerateEndHook
        (
            this MethodDefinition method,

            HookOptions options = HookOptions.Default,
            VariableDefinition result_variable = null
        )
        {
            // emit call at each ret instruction

            // add or get the types where we are storing out auto generated hooks & their delegates
            var hooks_type           = method.DeclaringType.GetHooksType();
            var hooks_delegates_type = method.DeclaringType.GetHooksDelegateType();

            // generate the hook handler delegate
            var hook_delegate_emitter = new HookDelegateEmitter("OnPost", method, options & ~(
                                                                    HookOptions.ReferenceParameters |
                                                                    HookOptions.Cancellable
                                                                    ));
            var hook_handler = hook_delegate_emitter.Emit();

            hooks_delegates_type.NestedTypes.Add(hook_handler);

            // generate the api hook external modules can attach to
            var hook_field = new FieldDefinition("Post" + method.GetSafeName(), FieldAttributes.Public | FieldAttributes.Static, hook_handler);

            hooks_type.Fields.Add(hook_field);

            // generate the call to the delegate
            var hook_emitter = new HookEmitter(hook_field, method, false, false, result_variable);
            var result       = hook_emitter.Emit();

            // end of method

            return(result);
        }