using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; namespace VCommon.Diagnostics { public static class StackTraceExtensionMethod { /// 将堆栈跟踪信息格式化成每一帧都带程序集的详情文本, 可指定一个type来忽略之上的调用堆栈帧 public static string GetFormattedDetailStackTraceText(this StackTrace me, Type skipUpper = null, bool hasSourceStackFrameOnly = false) { var rawFrames = me.GetFrames(); if (null == rawFrames) return null; var upperFrames = rawFrames; if (null != skipUpper) { var lst = new List(rawFrames.Length); for (var i = rawFrames.Length - 1; i >= 0; i--) { if (rawFrames[i].GetMethod().DeclaringType == skipUpper) break; lst.Insert(0, rawFrames[i]); } upperFrames = lst.ToArray(); } var sb = new StringBuilder(); var filteredFrames = upperFrames; if (hasSourceStackFrameOnly) { filteredFrames = upperFrames.Where(p => p.HasSource()).ToArray(); } foreach (var frame in filteredFrames) { var method = frame.GetMethod(); var type = method.DeclaringType; var asm = type?.Assembly; var filename = frame.GetFileName(); if (null != asm) sb.Append($"[{asm.GetName().Name}] "); if (null != type) sb.Append($"{type.FullName}::"); sb.Append($"{method}"); if (null != filename) sb.Append($" @ {filename}:{frame.GetFileLineNumber()},{frame.GetFileColumnNumber()}"); sb.AppendLine(); } return sb.ToString(); } } }