Callstack.cs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. using System;
  2. using System.Diagnostics;
  3. using System.Globalization;
  4. using System.Reflection;
  5. namespace WinSCP
  6. {
  7. internal class Callstack : IDisposable
  8. {
  9. public Callstack(Logger logger, object token = null)
  10. {
  11. _logger = logger;
  12. if (_logger.Logging)
  13. {
  14. _token = token;
  15. Type type = typeof(Callstack);
  16. StackTrace stackTrace = new StackTrace();
  17. int i = 0;
  18. MethodBase method;
  19. do
  20. {
  21. StackFrame frame = stackTrace.GetFrame(i);
  22. method = frame.GetMethod();
  23. if ((method.IsConstructor && IsTypeOrSubType(method.DeclaringType, type)) ||
  24. ((method.MemberType == MemberTypes.Method) && IsTypeOrSubType(((MethodInfo)method).ReturnType, type)))
  25. {
  26. method = null;
  27. }
  28. else
  29. {
  30. break;
  31. }
  32. i++;
  33. }
  34. while (i < stackTrace.FrameCount);
  35. if (method != null)
  36. {
  37. _name = string.Format(CultureInfo.InvariantCulture, "{0}.{1}", method.DeclaringType.Name, method.Name);
  38. if (_token != null)
  39. {
  40. _name += string.Format(CultureInfo.InvariantCulture, "({0})", _token);
  41. }
  42. _logger.WriteLine("{0} entering", _name);
  43. _logger.Indent();
  44. }
  45. }
  46. }
  47. private static bool IsTypeOrSubType(Type tested, Type type)
  48. {
  49. return (tested == type) || tested.IsSubclassOf(type);
  50. }
  51. public virtual void Dispose()
  52. {
  53. if (_name != null)
  54. {
  55. _logger.Unindent();
  56. _logger.WriteLine("{0} leaving", _name);
  57. }
  58. }
  59. private readonly Logger _logger;
  60. private readonly string _name;
  61. private readonly object _token;
  62. }
  63. }