请注意,这是对现有答案的改进。
这个问题的
Accepted answer 真的很笨拙,因为
- 它使用纯字符串通过名称确定我们需要从堆栈跟踪中隐藏的方法。
- 拆分堆栈跟踪基于
string.Split 方法。
- 它只隐藏了
StackTrace 属性中的一种方法,没有更多。
但它会覆盖 StackTrace 属性本身(这是问题的期望行为)
Most Upvoted Answer 非常干净,因为
- 它使用了一个属性,而不是将方法的名称指定为一个字符串。
- 它可用于对
StackTrace 隐藏多个方法。
但它真的很复杂,只是增加了两个类
用于扩展方法。
而且其中最重要的弱点不是压倒一切
StackTrace 属性本身。
在阅读了前两个解决方案之后,我想我达到了最简单和最干净的方式(结合了这个问题的两个最佳答案)
这是所需的基础设施。
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public sealed class StackTraceHiddenAttribute : Attribute
{
}
public class SomeException : Exception
{
public override string StackTrace
{
get
{
return string.Concat(
new StackTrace(this, true)
.GetFrames()
.Where(frame => !frame.GetMethod().IsDefined(typeof(StackTraceHiddenAttribute), true))
.Select(frame => new StackTrace(frame).ToString())
.ToArray());
}
}
}
这里是使用先前基础设施的示例
[StackTraceHidden] // apply this to all methods you want to be omitted in stack traces
static void Throw()
{
throw new SomeException();
}
static void Foo()
{
Throw();
}
static void Main()
{
try
{
Foo();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
}
}
编辑
根据@Stakx 对此答案的评论,在放置后立即删除,他指出了一些重要的想法:
此解决方案仅适用于自定义定义的异常,他的解决方案适用于所有异常类型,这是绝对正确的。
据此,这里有一种扩展方法,不需要复杂得多,它可以解决问题并适用于所有异常类型。
public static class ExceptionExtensions
{
public static string GetStackTraceWithoutHiddenMethods(this Exception e)
{
return string.Concat(
new StackTrace(e, true)
.GetFrames()
.Where(frame => !frame.GetMethod().IsDefined(typeof(StackTraceHiddenAttribute), true))
.Select(frame => new StackTrace(frame).ToString())
.ToArray());
}
}
这几乎与他的代码相同,除了集成了IsDefined 方法。