/// <summary>
        /// If can not find specified type or specified observer, do nothing.
        /// </summary>
        /// <param name="observer">If observer is null, do nothing.</param>
        /// <param name="method">If method is null, remove observer.</param>
        /// <param name="oncePerFrame">Specify to remove which listener in ExpandDelegate.</param>
        public void RemoveOncePerFrameListenerExt <T>(string type, object observer, Action <T[]> method = null) where T : ListenerData
        {
            if (observer == null || !mListenerDict.ContainsKey(type) || !mListenerDict[type].ContainsKey(observer))
            {
                return;
            }

            if (method == null)
            {
                mListenerDict[type].Remove(observer);
                return;
            }

            ExpandDelegate epDelegate = mListenerDict[type][observer];
            Delegate       listener   = epDelegate.OncePerFrameListener;

            if (listener == null)
            {
                Debugger.LogError("Listener is null!");
                return;
            }

            if (listener.GetType() != method.GetType())
            {
                Debugger.LogError("Incompatible delegate Types!");
                return;
            }

            epDelegate.OncePerFrameListener = Delegate.Remove(listener, method);
            if (epDelegate.Listener == null && epDelegate.OncePerFrameListener == null)
            {
                mListenerDict[type].Remove(observer);
            }
        }
        private bool ListenerAddingCheck(string type, object observer, Type argsType, bool oncePerFrame)
        {
            if (observer == null)
            {
                Debugger.LogError("Observer is null!");
                return(false);
            }

            if (!mListenerDict.ContainsKey(type))
            {
                Dictionary <object, ExpandDelegate> observerListenerDict = new Dictionary <object, ExpandDelegate>();
                observerListenerDict.Add(observer, new ExpandDelegate());
                mListenerDict.Add(type, observerListenerDict);
                return(true);
            }

            Dictionary <object, ExpandDelegate> dict = mListenerDict[type];

            if (!dict.ContainsKey(observer))
            {
                dict.Add(observer, new ExpandDelegate());
                return(true);
            }

            ExpandDelegate epDelegate = dict[observer];
            Delegate       listener   = oncePerFrame ? epDelegate.OncePerFrameListener : epDelegate.Listener;

            if (listener == null || listener.GetType() == argsType)
            {
                return(true);
            }

            Debugger.LogError("Incompatible delegate Types!");
            return(false);
        }
 /// <summary>
 /// </summary>
 /// <param name="type">The type which want to listen.</param>
 /// <param name="observer">The key is used to remove listener easily.</param>
 /// <param name="method">The method which want to invoke while event been triggered.</param>
 public void AddListenerExt(string type, object observer, Delegate method)
 {
     if (method != null && ListenerAddingCheck(type, observer, method.GetType(), false))
     {
         ExpandDelegate epDelegate = mListenerDict[type][observer];
         epDelegate.Listener = Delegate.Combine(epDelegate.Listener, method);
     }
 }
 /// <summary>
 /// Once-per-frame-listener will invoke once on end of current frame.
 /// </summary>
 /// <param name="type">The type which want to listen.</param>
 /// <param name="observer">The key is used to remove listener easily.</param>
 /// <param name="method">The method which want to invoke while event been triggered.</param>
 public void AddOncePerFrameListenerExt <T>(string type, object observer, Action <T[]> method) where T : ListenerData
 {
     if (method != null && ListenerAddingCheck(type, observer, typeof(Action <T[]>), true))
     {
         ExpandDelegate epDelegate = mListenerDict[type][observer];
         epDelegate.OncePerFrameListener = Delegate.Combine(epDelegate.OncePerFrameListener, method);
         epDelegate.OncePerFrameArgList  = new List <T>();
     }
 }