private static Tuple <MethodInfo, RedirectCallsState> RedirectMethod(Type targetType, MethodInfo detour, bool reverse)
        {
            String originalMethodName = detourRegex.Replace(detour.Name, "");

            try {
                BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
                var          parameters   = detour.GetParameters();
                Type[]       types;
                if (parameters.Length > 0 && (
                        (!targetType.IsValueType && parameters[0].ParameterType.Equals(targetType)) ||
                        (targetType.IsValueType && parameters[0].ParameterType.Equals(targetType.MakeByRefType()))))
                {
                    types = parameters.Skip(1).Select(p => p.ParameterType).ToArray();
                }
                else
                {
                    types = parameters.Select(p => p.ParameterType).ToArray();
                }
                var originalMethod = targetType.GetMethod(originalMethodName, bindingFlags, null, types, null);
                Log._Debug($"before redirect: originalMethod: {originalMethod.MethodHandle.GetFunctionPointer()} detour: {detour.MethodHandle.GetFunctionPointer()}");
                var redirectCallsState =
                    reverse ? RedirectionHelper.RedirectCalls(detour, originalMethod) : RedirectionHelper.RedirectCalls(originalMethod, detour);
                Log._Debug($"after redirect: originalMethod: {originalMethod.MethodHandle.GetFunctionPointer()} detour: {detour.MethodHandle.GetFunctionPointer()}");
                return(Tuple.New(reverse ? detour : originalMethod, redirectCallsState));
            } catch (Exception e) {
                Log.Error($"An error occurred while trying to {(reverse ? "reverse-" : "")}detour original method {targetType.FullName}.{originalMethodName} {(reverse ? "from" : "to")} {detour.ReflectedType.FullName}.{detour.Name}: {e.ToString()}");
                Log.Info(e.StackTrace);
                throw e;
            }
        }