[NUI] Unified native singleton class instance getter
authorEunki Hong <eunkiki.hong@samsung.com>
Tue, 20 Feb 2024 16:30:12 +0000 (01:30 +0900)
committerSangHyeon Jade Lee <dltkdgus1764@gmail.com>
Wed, 20 Mar 2024 11:19:40 +0000 (20:19 +0900)
There was 2 way to get sigleton class - `Get()` method and `Instance` proeprty.

After merge #5683 PR, some singleton class' `Get()` method register registry at that moment.
If someone call `Instance` after `Get()` call, the singleton class become GC, due to unknown reason.

To avoid this cases, let we make `Get()` method also use `Instance` property internally, and deprecate
that method.

For watch the trends after change the singletone pattern, let we just print error log if some
NUI developer implement wrong way in future.

+

Furthermore, there was some issue when we get Instance and call Dispose().
This is strance behavior. So let we just print error log and don't allow Dispose it.

Signed-off-by: Eunki Hong <eunkiki.hong@samsung.com>
src/Tizen.NUI/src/internal/Common/KeyInputFocusManager.cs
src/Tizen.NUI/src/public/Accessibility/AccessibilityManager.cs
src/Tizen.NUI/src/public/Clipboard/Clipboard.cs
src/Tizen.NUI/src/public/Common/StyleManager.cs
src/Tizen.NUI/src/public/Common/TypeRegistry.cs
src/Tizen.NUI/src/public/Input/FocusManager.cs
src/Tizen.NUI/src/public/Utility/FontClient.cs
src/Tizen.NUI/src/public/Utility/TTSPlayer.cs
src/Tizen.NUI/src/public/Visuals/VisualFactory.cs

index 4092380..2f9f0ce 100755 (executable)
@@ -21,6 +21,7 @@ namespace Tizen.NUI
 {
     internal class KeyInputFocusManager : BaseHandle
     {
+        private static readonly KeyInputFocusManager instance = KeyInputFocusManager.GetInternal();
         internal KeyInputFocusManager(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
         {
         }
@@ -35,13 +36,36 @@ namespace Tizen.NUI
             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
         }
 
+        /// <summary>
+        /// Gets the singleton of the KeyInputFocusManager object.
+        /// </summary>
+        public static KeyInputFocusManager Instance
+        {
+            get
+            {
+                return instance;
+            }
+        }
+
+        [global::System.Obsolete("Do not use this, that will be deprecated. Use KeyInputFocusManager.Instance instead.")]
         public static KeyInputFocusManager Get()
         {
+            return KeyInputFocusManager.Instance;
+        }
+
+        private static KeyInputFocusManager GetInternal()
+        {
             global::System.IntPtr cPtr = Interop.KeyInputFocusManager.Get();
 
+            if(cPtr == global::System.IntPtr.Zero)
+            {
+                NUILog.ErrorBacktrace("KeyInputFocusManager.Instance called before Application created, or after Application terminated!");
+            }
+
             KeyInputFocusManager ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as KeyInputFocusManager;
             if (ret != null)
             {
+                NUILog.ErrorBacktrace("KeyInputFocusManager.GetInternal() Should be called only one time!");
                 object dummyObect = new object();
 
                 global::System.Runtime.InteropServices.HandleRef CPtr = new global::System.Runtime.InteropServices.HandleRef(dummyObect, cPtr);
@@ -57,6 +81,18 @@ namespace Tizen.NUI
             return ret;
         }
 
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                NUILog.ErrorBacktrace("We should not manually dispose for singleton class!");
+            }
+            else
+            {
+                base.Dispose(disposing);
+            }
+        }
+
         public void SetFocus(View control)
         {
             Interop.KeyInputFocusManager.SetFocus(SwigCPtr, View.getCPtr(control));
index bd8b15a..c4eb2a9 100755 (executable)
@@ -31,7 +31,7 @@ namespace Tizen.NUI.Accessibility
     [EditorBrowsable(EditorBrowsableState.Never)]
     public partial class AccessibilityManager : BaseHandle
     {
-        private static readonly AccessibilityManager instance = AccessibilityManager.Get();
+        private static readonly AccessibilityManager instance = AccessibilityManager.GetInternal();
 
         internal AccessibilityManager(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
         {
@@ -698,13 +698,25 @@ namespace Tizen.NUI.Accessibility
             return ret;
         }
 
+        [Obsolete("Do not use this, that will be deprecated. Use AccessibilityManager.Instance instead.")]
         internal static AccessibilityManager Get()
         {
+            return AccessibilityManager.Instance;
+        }
+
+        private static AccessibilityManager GetInternal()
+        {
             global::System.IntPtr cPtr = Interop.AccessibilityManager.Get();
 
+            if(cPtr == global::System.IntPtr.Zero)
+            {
+                NUILog.ErrorBacktrace("AccessibilityManager.Instance called before Application created, or after Application terminated!");
+            }
+
             AccessibilityManager ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as AccessibilityManager;
             if (ret != null)
             {
+                NUILog.ErrorBacktrace("AccessibilityManager.GetInternal() Should be called only one time!");
                 object dummyObect = new object();
 
                 global::System.Runtime.InteropServices.HandleRef CPtr = new global::System.Runtime.InteropServices.HandleRef(dummyObect, cPtr);
@@ -720,6 +732,19 @@ namespace Tizen.NUI.Accessibility
             return ret;
         }
 
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                NUILog.ErrorBacktrace("We should not manually dispose for singleton class!");
+            }
+            else
+            {
+                base.Dispose(disposing);
+            }
+        }
+
         // Signals - AccessibilityManagerEvent.cs
         internal FocusChangedSignal FocusChangedSignal()
         {
index 887ca9a..c0f84f8 100755 (executable)
@@ -31,6 +31,8 @@ namespace Tizen.NUI
     [EditorBrowsable(EditorBrowsableState.Never)]
     public partial class Clipboard : BaseHandle
     {
+        private static readonly Clipboard instance = Clipboard.GetInternal();
+
         /// <summary>
         /// User callback for clipboard event.
         /// </summary>
@@ -42,11 +44,6 @@ namespace Tizen.NUI
         internal bool hasClipboardDataReceived = false;
         internal Dictionary<uint, ClipboardCallback> receivedCallbackDictionary = new Dictionary<uint, ClipboardCallback>();
 
-        private Clipboard() : this(Interop.Clipboard.Get(), true)
-        {
-            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
-        }
-
         private Clipboard(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
         {
         }
@@ -55,7 +52,55 @@ namespace Tizen.NUI
         /// Gets the singleton instance of Clipboard.
         /// </summary>
         [EditorBrowsable(EditorBrowsableState.Never)]
-        public static Clipboard Instance { get; } = new Clipboard();
+        public static Clipboard Instance
+        {
+            get
+            {
+                return instance;
+            }
+        }
+
+        private static Clipboard GetInternal()
+        {
+            global::System.IntPtr cPtr = Interop.Clipboard.Get();
+
+            if(cPtr == global::System.IntPtr.Zero)
+            {
+                NUILog.ErrorBacktrace("Clipboard.Instance called before Application created, or after Application terminated!");
+                // Do not throw exception until TCT test passed.
+            }
+
+            Clipboard ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as Clipboard;
+            if (ret != null)
+            {
+                NUILog.ErrorBacktrace("Clipboard.GetInternal() Should be called only one time!");
+                object dummyObect = new object();
+
+                HandleRef CPtr = new HandleRef(dummyObect, cPtr);
+                Interop.BaseHandle.DeleteBaseHandle(CPtr);
+                CPtr = new HandleRef(null, global::System.IntPtr.Zero);
+            }
+            else
+            {
+                ret = new Clipboard(cPtr, true);
+            }
+
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return ret;
+        }
+
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                NUILog.ErrorBacktrace("We should not manually dispose for singleton class!");
+            }
+            else
+            {
+                base.Dispose(disposing);
+            }
+        }
 
         /// <summary>
         /// Request set the given data to the clipboard.
index 85dcd4c..55a7596 100755 (executable)
@@ -33,7 +33,7 @@ namespace Tizen.NUI
     [Obsolete("Deprecated in API9, will be removed in API11. Use ThemeManager instead.")]
     public class StyleManager : BaseHandle
     {
-        private static readonly StyleManager instance = StyleManager.Get();
+        private static readonly StyleManager instance = StyleManager.GetInternal();
         private EventHandler<StyleChangedEventArgs> styleManagerStyleChangedEventHandler;
         private StyleChangedCallbackDelegate styleManagerStyleChangedCallbackDelegate;
 
@@ -98,14 +98,27 @@ namespace Tizen.NUI
         /// </summary>
         /// <returns>A handle to the StyleManager control.</returns>
         /// <since_tizen> 3 </since_tizen>
-        [Obsolete("Deprecated in API9, will be removed in API11. Use ThemeManager instead.")]
+        [Obsolete("Deprecated in API9, will be removed in API11. Use ThemeManager instead." +
+            "Do not use this, that will be deprecated. Use StyleManager.Instance instead.")]
         public static StyleManager Get()
         {
+            return StyleManager.Instance;
+        }
+
+        private static StyleManager GetInternal()
+        {
             global::System.IntPtr cPtr = Interop.StyleManager.Get();
 
+            if(cPtr == global::System.IntPtr.Zero)
+            {
+                NUILog.ErrorBacktrace("StyleManager.Instance called before Application created, or after Application terminated!");
+                // Do not throw exception until TCT test passed.
+            }
+
             StyleManager ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as StyleManager;
             if (ret != null)
             {
+                NUILog.ErrorBacktrace("StyleManager.GetInternal() Should be called only one time!");
                 object dummyObect = new object();
 
                 HandleRef CPtr = new HandleRef(dummyObect, cPtr);
@@ -121,6 +134,19 @@ namespace Tizen.NUI
             return ret;
         }
 
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                NUILog.ErrorBacktrace("We should not manually dispose for singleton class!");
+            }
+            else
+            {
+                base.Dispose(disposing);
+            }
+        }
+
         /// <summary>
         /// Applies a new theme to the application.<br />
         /// This will be merged on the top of the default Toolkit theme.<br />
index 2733b18..8c40acb 100755 (executable)
@@ -26,6 +26,7 @@ namespace Tizen.NUI
     [EditorBrowsable(EditorBrowsableState.Never)]
     public class TypeRegistry : BaseHandle
     {
+        private static readonly TypeRegistry instance = TypeRegistry.GetInternal();
         internal TypeRegistry(global::System.IntPtr cPtr, bool cMemoryOwn) : this(cPtr, cMemoryOwn, cMemoryOwn)
         {
         }
@@ -42,18 +43,43 @@ namespace Tizen.NUI
         }
 
         /// <summary>
+        /// Gets the singleton of the TypeRegistry object.
+        /// </summary>
+        /// This will be public opened in next tizen after ACR done. Before ACR, need to be hidden as inhouse API.
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static TypeRegistry Instance
+        {
+            get
+            {
+                return instance;
+            }
+        }
+
+        /// <summary>
         /// Gets Type Registry handle.
         /// </summary>
         /// <returns>TypeRegistry handle.</returns>
         /// This will be public opened in next tizen after ACR done. Before ACR, need to be hidden as inhouse API.
+        [global::System.Obsolete("Do not use this, that will be deprecated. Use TypeRegistry.Instance instead.")]
         [EditorBrowsable(EditorBrowsableState.Never)]
         public static TypeRegistry Get()
         {
+            return TypeRegistry.Instance;
+        }
+
+        private static TypeRegistry GetInternal()
+        {
             global::System.IntPtr cPtr = Interop.TypeRegistry.Get();
 
+            if(cPtr == global::System.IntPtr.Zero)
+            {
+                NUILog.ErrorBacktrace("TypeRegistry.Instance called before Application created, or after Application terminated!");
+            }
+
             TypeRegistry ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as TypeRegistry;
             if (ret != null)
             {
+                NUILog.ErrorBacktrace("TypeRegistry.GetInternal() Should be called only one time!");
                 object dummyObect = new object();
 
                 global::System.Runtime.InteropServices.HandleRef CPtr = new global::System.Runtime.InteropServices.HandleRef(dummyObect, cPtr);
@@ -69,6 +95,19 @@ namespace Tizen.NUI
             return ret;
         }
 
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                NUILog.ErrorBacktrace("We should not manually dispose for singleton class!");
+            }
+            else
+            {
+                base.Dispose(disposing);
+            }
+        }
+
         /// <summary>
         /// Allows the creation of an empty typeRegistry handle.
         /// </summary>
index 3a692f3..59d5cc6 100755 (executable)
@@ -30,7 +30,7 @@ namespace Tizen.NUI
     /// <since_tizen> 3 </since_tizen>
     public class FocusManager : BaseHandle
     {
-        private static readonly FocusManager instance = FocusManager.Get();
+        private static readonly FocusManager instance = FocusManager.GetInternal();
         private CustomAlgorithmInterfaceWrapper customAlgorithmInterfaceWrapper;
 
         private EventHandlerWithReturnType<object, PreFocusChangeEventArgs, View> preFocusChangeEventHandler;
@@ -602,9 +602,39 @@ namespace Tizen.NUI
             return ret;
         }
 
+        [global::System.Obsolete("Do not use this, that will be deprecated. Use TypeRegistry.Instance instead. " +
+            "Like: " +
+            "TypeRegistry visualFactory = TypeRegistry.Instance; " +
+            "TypeRegistry.CreateVisual(visualMap);")]
         internal static FocusManager Get()
         {
-            FocusManager ret = new FocusManager(Interop.FocusManager.Get(), true);
+            return FocusManager.Instance;
+        }
+
+        private static FocusManager GetInternal()
+        {
+            global::System.IntPtr cPtr = Interop.FocusManager.Get();
+
+            if(cPtr == global::System.IntPtr.Zero)
+            {
+                NUILog.ErrorBacktrace("FocusManager.Instance called before Application created, or after Application terminated!");
+            }
+
+            FocusManager ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as FocusManager;
+            if (ret != null)
+            {
+                NUILog.ErrorBacktrace("FocusManager.GetInternal() Should be called only one time!");
+                object dummyObect = new object();
+
+                global::System.Runtime.InteropServices.HandleRef CPtr = new global::System.Runtime.InteropServices.HandleRef(dummyObect, cPtr);
+                Interop.BaseHandle.DeleteBaseHandle(CPtr);
+                CPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero);
+            }
+            else
+            {
+                ret = new FocusManager(cPtr, true);
+            }
+
             if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
 
 #if !PROFILE_TV
@@ -614,6 +644,19 @@ namespace Tizen.NUI
             return ret;
         }
 
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                NUILog.ErrorBacktrace("We should not manually dispose for singleton class!");
+            }
+            else
+            {
+                base.Dispose(disposing);
+            }
+        }
+
         internal void SetFocusGroupLoop(bool enabled)
         {
             Interop.FocusManager.SetFocusGroupLoop(SwigCPtr, enabled);
index 7fb9c8a..95cd90e 100755 (executable)
@@ -27,7 +27,7 @@ namespace Tizen.NUI
     /// <since_tizen> 5 </since_tizen>
     public class FontClient : BaseHandle
     {
-        private static readonly FontClient instance = FontClient.Get();
+        private static readonly FontClient instance = FontClient.GetInternal();
 
         internal FontClient(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
         {
@@ -284,13 +284,28 @@ namespace Tizen.NUI
             return fontInfoList;
         }
 
+        [global::System.Obsolete("Do not use this, that will be deprecated. Use FontClient.Instance instead. " +
+            "Like: " +
+            "FontClient fontClient = FontClient.Instance; " +
+            "FontClient.GetSystemFonts();")]
         internal static FontClient Get()
         {
+            return FontClient.Instance;
+        }
+
+        private static FontClient GetInternal()
+        {
             global::System.IntPtr cPtr = Interop.FontClient.Get();
 
+            if(cPtr == global::System.IntPtr.Zero)
+            {
+                NUILog.ErrorBacktrace("FontClient.Instance called before Application created, or after Application terminated!");
+            }
+
             FontClient ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as FontClient;
             if (ret != null)
             {
+                NUILog.ErrorBacktrace("FontClient.GetInternal() Should be called only one time!");
                 object dummyObect = new object();
 
                 global::System.Runtime.InteropServices.HandleRef CPtr = new global::System.Runtime.InteropServices.HandleRef(dummyObect, cPtr);
@@ -306,6 +321,19 @@ namespace Tizen.NUI
             return ret;
         }
 
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                NUILog.ErrorBacktrace("We should not manually dispose for singleton class!");
+            }
+            else
+            {
+                base.Dispose(disposing);
+            }
+        }
+
         internal FontClient Assign(FontClient handle)
         {
             FontClient ret = new FontClient(Interop.FontClient.Assign(SwigCPtr, FontClient.getCPtr(handle)), false);
index 7c45988..5d8bec1 100755 (executable)
@@ -27,7 +27,7 @@ namespace Tizen.NUI
     /// <since_tizen> 3 </since_tizen>
     public class TTSPlayer : BaseHandle
     {
-        private static readonly TTSPlayer instance = TTSPlayer.Get();
+        private static readonly TTSPlayer[] instance = {TTSPlayer.GetInternal(TTSMode.Default), TTSPlayer.GetInternal(TTSMode.Notification), TTSPlayer.GetInternal(TTSMode.ScreenReader)};
         private StateChangedEventCallbackType stateChangedEventCallback;
 
         internal TTSPlayer(global::System.IntPtr cPtr, bool cMemoryOwn) : this(cPtr, cMemoryOwn, cMemoryOwn)
@@ -137,7 +137,7 @@ namespace Tizen.NUI
         {
             get
             {
-                return instance;
+                return instance[(int)TTSMode.Default];
             }
         }
 
@@ -149,24 +149,7 @@ namespace Tizen.NUI
         /// <since_tizen> 3 </since_tizen>
         public static TTSPlayer Get(TTSMode mode)
         {
-            global::System.IntPtr cPtr = Interop.TtsPlayer.Get((int)mode);
-
-            TTSPlayer ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as TTSPlayer;
-            if (ret != null)
-            {
-                object dummyObect = new object();
-
-                HandleRef CPtr = new HandleRef(dummyObect, cPtr);
-                Interop.BaseHandle.DeleteBaseHandle(CPtr);
-                CPtr = new HandleRef(null, global::System.IntPtr.Zero);
-            }
-            else
-            {
-                ret = new TTSPlayer(cPtr, true);
-            }
-
-            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
-            return ret;
+            return instance[(int)mode];
         }
 
         /// <summary>
@@ -176,11 +159,22 @@ namespace Tizen.NUI
         /// <since_tizen> 3 </since_tizen>
         public static TTSPlayer Get()
         {
-            global::System.IntPtr cPtr = Interop.TtsPlayer.Get();
+            return TTSPlayer.Instance;
+        }
+
+        private static TTSPlayer GetInternal(TTSMode mode)
+        {
+            global::System.IntPtr cPtr = Interop.TtsPlayer.Get((int) mode);
+
+            if(cPtr == global::System.IntPtr.Zero)
+            {
+                NUILog.ErrorBacktrace("TTSPlayer.Instance called before Application created, or after Application terminated!");
+            }
 
             TTSPlayer ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as TTSPlayer;
             if (ret != null)
             {
+                NUILog.ErrorBacktrace("TTSPlayer.GetInternal() Should be called only one time!");
                 object dummyObect = new object();
 
                 HandleRef CPtr = new HandleRef(dummyObect, cPtr);
@@ -196,6 +190,19 @@ namespace Tizen.NUI
             return ret;
         }
 
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                NUILog.ErrorBacktrace("We should not manually dispose for singleton class!");
+            }
+            else
+            {
+                base.Dispose(disposing);
+            }
+        }
+
         /// <summary>
         /// Starts playing the audio data synthesized from the specified text.
         /// </summary>
index ef365ad..7fb9c8d 100755 (executable)
@@ -29,7 +29,7 @@ namespace Tizen.NUI
         /// <summary>
         /// Instance of the VisualFactory singleton.
         /// </summary>
-        private static VisualFactory instance;
+        private static readonly VisualFactory instance = VisualFactory.GetInternal();
 
         private VisualFactory(global::System.IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
         {
@@ -48,12 +48,6 @@ namespace Tizen.NUI
         {
             get
             {
-                if (!instance)
-                {
-                    instance = new VisualFactory(Interop.VisualFactory.Get(), true);
-                    if (NDalicPINVOKE.SWIGPendingException.Pending) throw new InvalidOperationException("FATAL: get Exception", NDalicPINVOKE.SWIGPendingException.Retrieve());
-                }
-
                 return instance;
             }
         }
@@ -72,6 +66,47 @@ namespace Tizen.NUI
             return VisualFactory.Instance;
         }
 
+        private static VisualFactory GetInternal()
+        {
+            global::System.IntPtr cPtr = Interop.VisualFactory.Get();
+
+            if(cPtr == global::System.IntPtr.Zero)
+            {
+                NUILog.ErrorBacktrace("VisualFactory.Instance called before Application created, or after Application terminated!");
+            }
+
+            VisualFactory ret = Registry.GetManagedBaseHandleFromNativePtr(cPtr) as VisualFactory;
+            if (ret != null)
+            {
+                NUILog.ErrorBacktrace("VisualFactory.GetInternal() Should be called only one time!");
+                object dummyObect = new object();
+
+                global::System.Runtime.InteropServices.HandleRef CPtr = new global::System.Runtime.InteropServices.HandleRef(dummyObect, cPtr);
+                Interop.BaseHandle.DeleteBaseHandle(CPtr);
+                CPtr = new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero);
+            }
+            else
+            {
+                ret = new VisualFactory(cPtr, true);
+            }
+
+            if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
+            return ret;
+        }
+
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                NUILog.ErrorBacktrace("We should not manually dispose for singleton class!");
+            }
+            else
+            {
+                base.Dispose(disposing);
+            }
+        }
+
         /// <summary>
         /// Request the visual.
         /// </summary>