在运行时备份堆栈跟踪

Back up stacktrace at runtime

这似乎是一个奇怪的问题,但 google 没有给我任何继续下去的东西。

我有一些扩展方法可以让我根据需要评估 return 值等。我在 Contracts 不能真正按照我的意愿行事的地方使用它们。

这些扩展方法所做的是老式 Debug.Assert() 和 'for realsies' 检查的组合,如果不满足条件则抛出异常。我还有其他方法也允许您抛出特定异常。示例:

public static void IsNotNullOrEmpty(this System.Collections.ICollection input, string message = default(string), bool throwOnFailure = true)
            {
                if (!string.IsNullOrEmpty(message))
                    Debug.Assert(input != null && input.Count > 0, message);

                if (input == null || input.Count == 0 && throwOnFailure)
                    throw new ArgumentNullException(message);
            }

        public static void IsNotNull<T>(this object input, string message = default(string), bool throwOnFailure = true)  where T : Exception, new()
        {
            if (!string.IsNullOrEmpty(message))
                Debug.Assert(input != null, message);

            if (input == null && throwOnFailure)
            {
                // NOTE - catches the possibility that the Exception class's implementation does not have a constructor that takes a message
                // Have to do it this way because the Message property is readonly on the Exception class so we can't just set it.
                try 
                {
                    throw Activator.CreateInstance(typeof(T), message) as T;
                } 
                catch(MissingMethodException)  
                {
                    throw new T();
                }
            }
        }

他们实际上工作得很好。唯一的问题是调试断言将调试器捕捉到 Debug.Assert() 行。我希望它捕捉到实际违反约束的线上。

所以我的问题是,我可以轻松地在堆栈跟踪上使用 .GetFrame(1) 来获取调用约束的方法的 MethodInfo。但是我如何让 VS 中的调试器备份一帧并显示该方法,就像您在调用堆栈中双击它一样 window?

很可能有一种方法可以用 Nuget 上的一些预先打包的东西或你有什么来做到这一点,但到目前为止这些对我来说非常有用。

有人有想法吗?

谢谢 E

我只是想知道你是不是这个意思。这将返回方法的名称和 Class 从中调用程序。

public static bool IsNull(this string value)
{
    var method = new StackTrace().GetFrame(1).GetMethod();
    Console.WriteLine(String.Format("I was called from '{0}' of class '{1}'", method.Name, method.DeclaringType));

    return string.IsNullOrEmpty(value);
}

你要的是DebuggerStepThroughAttribute.

当使用此属性标记的方法中抛出异常时,调试器将放置在调用该方法的行上,而不是在方法内部。

换句话说,您想这样声明您的方法:

[DebuggerStepThrough]
public static void IsNotNullOrEmpty(...)
{
    ...
}

[DebuggerStepThrough]
public static void IsNotNull<T>(...)
    where T : Exception, new()
{
    ...
}

另请注意,如果您在调试器中使用 step into 函数,您将不会单步执行这些方法之一,而是将其作为外部方法单步执行,这将使调试 这些 方法更难。

您可能需要考虑将该属性放在 #ifdef...#endig 部分中,以便轻松切换到允许调试它们的配置。