You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

78 lines
2.5 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. namespace IPA.Utilities
  9. {
  10. /// <summary>
  11. /// A class to store a reference for passing to methods which cannot take ref parameters.
  12. /// </summary>
  13. /// <typeparam name="T">the type of the value</typeparam>
  14. public class Ref<T>
  15. {
  16. private T _value;
  17. /// <summary>
  18. /// The value of the reference
  19. /// </summary>
  20. public T Value
  21. {
  22. get
  23. {
  24. if (Error != null) throw Error;
  25. return _value;
  26. }
  27. set => _value = value;
  28. }
  29. private Exception _error = null;
  30. /// <summary>
  31. /// An exception that was generated while creating the value.
  32. /// </summary>
  33. public Exception Error
  34. {
  35. get
  36. {
  37. return _error;
  38. }
  39. set
  40. {
  41. value.SetStackTrace(new StackTrace(1));
  42. _error = value;
  43. }
  44. }
  45. /// <summary>
  46. /// Constructor.
  47. /// </summary>
  48. /// <param name="reference">the initial value of the reference</param>
  49. public Ref(T reference)
  50. {
  51. _value = reference;
  52. }
  53. /// <summary>
  54. /// Throws error if one was set.
  55. /// </summary>
  56. public void Verify()
  57. {
  58. if (Error != null) throw new Exception("Found error", Error);
  59. }
  60. }
  61. internal static class ExceptionUtilities
  62. {
  63. private static readonly FieldInfo STACK_TRACE_STRING_FI = typeof(Exception).GetField("_stackTraceString", BindingFlags.NonPublic | BindingFlags.Instance);
  64. private static readonly Type TRACE_FORMAT_TI = Type.GetType("System.Diagnostics.StackTrace").GetNestedType("TraceFormat", BindingFlags.NonPublic);
  65. private static readonly MethodInfo TRACE_TO_STRING_MI = typeof(StackTrace).GetMethod("ToString", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { TRACE_FORMAT_TI }, null);
  66. public static Exception SetStackTrace(this Exception target, StackTrace stack)
  67. {
  68. var getStackTraceString = TRACE_TO_STRING_MI.Invoke(stack, new object[] { Enum.GetValues(TRACE_FORMAT_TI).GetValue(0) });
  69. STACK_TRACE_STRING_FI.SetValue(target, getStackTraceString);
  70. return target;
  71. }
  72. }
  73. }