Application.Lifecycle.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. using System.Collections.ObjectModel;
  2. using System.Diagnostics;
  3. using System.Diagnostics.CodeAnalysis;
  4. using System.Reflection;
  5. using Microsoft.VisualBasic;
  6. using Terminal.Gui.App;
  7. using Terminal.Gui.Drivers;
  8. using Terminal.Gui.Views;
  9. namespace Terminal.Gui.App;
  10. public static partial class Application // Lifecycle (Init/Shutdown)
  11. {
  12. /// <summary>
  13. /// Gets the observable collection of all application instances.
  14. /// External observers can subscribe to this collection to monitor application lifecycle.
  15. /// </summary>
  16. public static ObservableCollection<IApplication> Apps { get; } = [];
  17. /// <summary>
  18. /// Gets the singleton <see cref="IApplication"/> instance used by the legacy static Application model.
  19. /// </summary>
  20. /// <remarks>
  21. /// <para>
  22. /// For new code, prefer using <see cref="Create"/> to get an instance-based application.
  23. /// This property is provided for backward compatibility and internal use.
  24. /// </para>
  25. /// <para>
  26. /// This property returns the same singleton instance used by the legacy static <see cref="Application"/>
  27. /// methods like <see cref="Init"/> and <see cref="Run(IRunnable, Func{Exception, bool}?)"/>.
  28. /// </para>
  29. /// </remarks>
  30. [Obsolete ("The legacy static Application object is going away. Use Application.Create() for new code.")]
  31. public static IApplication Instance => ApplicationImpl.Instance;
  32. /// <summary>
  33. /// Creates a new <see cref="IApplication"/> instance.
  34. /// </summary>
  35. /// <param name="example">
  36. /// If <see langword="true"/>, the application will run in example mode where metadata is collected
  37. /// and demo keys are automatically sent when the first TopRunnable is modal.
  38. /// </param>
  39. /// <remarks>
  40. /// The recommended pattern is for developers to call <c>Application.Create()</c> and then use the returned
  41. /// <see cref="IApplication"/> instance for all subsequent application operations.
  42. /// </remarks>
  43. /// <returns>A new <see cref="IApplication"/> instance.</returns>
  44. /// <exception cref="InvalidOperationException">
  45. /// Thrown if the legacy static Application model has already been used in this process.
  46. /// </exception>
  47. public static IApplication Create (bool example = false)
  48. {
  49. //Debug.Fail ("Application.Create() called");
  50. ApplicationImpl.MarkInstanceBasedModelUsed ();
  51. ApplicationImpl app = new ();
  52. Apps.Add (app);
  53. return app;
  54. }
  55. /// <inheritdoc cref="IApplication.Init"/>
  56. [RequiresUnreferencedCode ("AOT")]
  57. [RequiresDynamicCode ("AOT")]
  58. [Obsolete ("The legacy static Application object is going away.")]
  59. public static void Init (string? driverName = null)
  60. {
  61. //Debug.Fail ("Application.Init() called - parallelizable tests should not use legacy static Application model");
  62. ApplicationImpl.Instance.Init (driverName ?? ForceDriver);
  63. }
  64. /// <summary>
  65. /// Gets or sets the main thread ID for the application.
  66. /// </summary>
  67. [Obsolete ("The legacy static Application object is going away.")]
  68. public static int? MainThreadId
  69. {
  70. get => ApplicationImpl.Instance.MainThreadId;
  71. internal set => ApplicationImpl.Instance.MainThreadId = value;
  72. }
  73. /// <inheritdoc cref="IDisposable.Dispose"/>
  74. [Obsolete ("The legacy static Application object is going away.")]
  75. public static void Shutdown () => ApplicationImpl.Instance.Dispose ();
  76. /// <inheritdoc cref="IApplication.Initialized"/>
  77. [Obsolete ("The legacy static Application object is going away.")]
  78. public static bool Initialized
  79. {
  80. get => ApplicationImpl.Instance.Initialized;
  81. internal set => ApplicationImpl.Instance.Initialized = value;
  82. }
  83. /// <inheritdoc cref="IApplication.InitializedChanged"/>
  84. [Obsolete ("The legacy static Application object is going away.")]
  85. public static event EventHandler<EventArgs<bool>>? InitializedChanged
  86. {
  87. add => ApplicationImpl.Instance.InitializedChanged += value;
  88. remove => ApplicationImpl.Instance.InitializedChanged -= value;
  89. }
  90. // IMPORTANT: Ensure all property/fields are reset here. See Init_ResetState_Resets_Properties unit test.
  91. // Encapsulate all setting of initial state for Application; Having
  92. // this in a function like this ensures we don't make mistakes in
  93. // guaranteeing that the state of this singleton is deterministic when Init
  94. // starts running and after Shutdown returns.
  95. [Obsolete ("The legacy static Application object is going away.")]
  96. internal static void ResetState (bool ignoreDisposed = false)
  97. {
  98. // Use the static reset method to bypass the fence check
  99. ApplicationImpl.ResetStateStatic (ignoreDisposed);
  100. }
  101. }