在运行时备份堆栈跟踪
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
部分中,以便轻松切换到允许调试它们的配置。
这似乎是一个奇怪的问题,但 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
部分中,以便轻松切换到允许调试它们的配置。