这个挺好的。值得一看
出处:http://blog.csdn.net/u010019717
author:孙广东 时间:2015.3.21 23:00
不使用C#中的event关键字: 只是使用delegate和hashtable 进行事件的分发。
基本库如下:
- namespace EventDispatcher
- {
- /// <summary>
- /// IEvent接口
- /// </summary>
- public interface IEvent
- {
- /// <summary>
- /// Gets or sets the type.
- /// </summary>
- /// <value>
- /// type类型.
- /// </value>
- string type { get; set;}
- /// <summary>
- /// Gets or sets the target.
- /// </summary>
- /// <value>
- /// target目标.
- /// </value>
- object target { get; set; }
- }
- }
- namespace EventDispatcher
- {
- /// <summary>
- /// 事件事件接口
- /// </summary>
- public class Event : IEvent
- {
- // GETTER / SETTER
- /// <summary>
- /// The _type_string.
- /// </summary>
- private string _type_string;
- string IEvent.type {
- get
- {
- return _type_string;
- }
- set
- {
- _type_string = value;
- }
- }
- /// <summary>
- /// The _target_object.
- /// </summary>
- private object _target_object;
- object IEvent.target {
- get
- {
- return _target_object;
- }
- set
- {
- _target_object = value;
- }
- }
- ///<summary>
- /// Constructor
- ///</summary>
- public Event (string aType_str )
- {
- //
- _type_string = aType_str;
- }
- /// <summary>
- /// Deconstructor
- /// </summary>
- //~Event ( )
- //{
- // Debug.Log ("Event.deconstructor()");
- //}
- }
- }
- namespace EventDispatcher
- {
- /// <summary>
- /// IEventDispatcher 事件分发接口,添加移除分发
- /// </summary>
- public interface IEventDispatcher
- {
- /// <summary>
- /// 添加事件监听
- /// </summary>
- /// <returns><c>true</c>, 如果事件成功被监听, <c>false</c> 失败 </returns>
- /// <param name="aEventType_string">A event type_string.</param>
- /// <param name="aEventDelegate">一个事件委托</param>
- bool addEventListener(string aEventType_string, EventDelegate aEventDelegate);
- /// <summary>
- /// 添加事件监听
- /// </summary>
- /// <returns><c>true</c>, 如果事件成功被监听, <c>false</c> 失败 </returns>
- /// <param name="aEventType_string">A event type_string.</param>
- /// <param name="aEventDelegate">一个事件委托</param>
- /// <param name="eventDispatcherAddMode">Event dispatcher add mode.</param>
- bool addEventListener(string aEventType_string, EventDelegate aEventDelegate, EventDispatcherAddMode eventDispatcherAddMode);
- /// <summary>
- /// 是否有这个事件监听
- /// </summary>
- /// <returns><c>true</c>, 这个监听已经有了, <c>false</c> 没有.</returns>
- /// <param name="aEventType_string">A event type_string.</param>
- /// <param name="aEventDelegate">一个事件委托</param>
- bool hasEventListener(string aEventType_string, EventDelegate aEventDelegate);
- /// <summary>
- /// 移除事件监听
- /// </summary>
- /// <returns><c>true</c>, 被成功移除 <c>false</c> 失败</returns>
- /// <param name="aEventType_string">A event type_string.</param>
- /// <param name="aEventDelegate">一个事件委托</param>
- bool removeEventListener(string aEventType_string, EventDelegate aEventDelegate);
- /// <summary>
- /// 移除所有事件监听
- /// </summary>
- /// <returns><c>true</c>, 成功, <c>false</c> 失败 </returns>
- bool removeAllEventListeners();
- /// <summary>
- /// 分发广播事件
- /// </summary>
- /// <returns><c>true</c>, 成功, <c>false</c> 失败</returns>
- /// <param name="aIEvent">A I event.</param>
- bool dispatchEvent(IEvent aIEvent);
- }
- }
- // C# unity事件管理器 在哈希表中使用字符串,对委托和事件管理
- // 不知道他们何时何地declared/defined 也允许使用事件。
- using UnityEngine;
- using System.Collections;
- namespace EventDispatcher
- {
- /// <summary>
- /// Event delegateN事件委托
- /// </summary>
- public delegate void EventDelegate ( IEvent iEvent );
- /// <summary>
- /// Event listening mode.
- /// </summary>
- public enum EventDispatcherAddMode
- {
- DEFAULT,
- SINGLE_SHOT
- }
- public class EventDispatcher : IEventDispatcher
- {
- /// <summary>
- /// The mom_serialized object.
- /// </summary>
- private Hashtable _eventListenerDatas_hashtable = new Hashtable();
- /// <summary>
- /// The _target_object.
- /// </summary>
- private object _target_object;
- ///<summary>
- /// Constructor
- ///</summary>
- public EventDispatcher (object aTarget_object )
- {
- //
- _target_object = aTarget_object;
- }
- /// <summary>
- /// Deconstructor
- /// </summary>
- //~EventDispatcher ( )
- //{
- // Debug.Log ("EventDispatcher.deconstructor()");
- //}
- /// <summary>
- /// Adds the event listener.
- /// </summary>
- /// <returns>
- /// The event listener.
- /// </returns>
- /// <param name='aEventName_string'>
- /// If set to <c>true</c> a event name_string.
- /// </param>
- /// <param name='aEventDelegate'>
- /// If set to <c>true</c> a event delegate.
- /// </param>
- public bool addEventListener(string aEventName_string, EventDelegate aEventDelegate)
- {
- return addEventListener (aEventName_string, aEventDelegate, EventDispatcherAddMode.DEFAULT);
- }
- /// <summary>
- /// Adds the event listener.
- /// </summary>
- /// <returns>
- /// The event listener.
- /// </returns>
- /// <param name='aEventName_string'>
- /// If set to <c>true</c> a event type_string.
- /// </param>
- /// <param name='aEventDelegate'>
- /// If set to <c>true</c> a event delegate.
- /// </param>
- /// <param name='aEventDispatcherAddMode'>
- /// If set to <c>true</c> event listening mode.
- /// </param>
- public bool addEventListener(string aEventName_string, EventDelegate aEventDelegate, EventDispatcherAddMode aEventDispatcherAddMode)
- {
- //
- bool wasSuccessful_boolean = false;
- //
- object aIEventListener = _getArgumentsCallee(aEventDelegate);
- //
- if (aIEventListener != null && aEventName_string != null) {
- // OUTER
- string keyForOuterHashTable_string = _getKeyForOuterHashTable (aEventName_string);
- if (!_eventListenerDatas_hashtable.ContainsKey(keyForOuterHashTable_string) ) {
- _eventListenerDatas_hashtable.Add(keyForOuterHashTable_string, new Hashtable());
- }
- // INNER
- Hashtable inner_hashtable = _eventListenerDatas_hashtable[keyForOuterHashTable_string] as Hashtable;
- EventListenerData eventListenerData = new EventListenerData (aIEventListener, aEventName_string, aEventDelegate, aEventDispatcherAddMode);
- //
- string keyForInnerHashTable_string = _getKeyForInnerHashTable (eventListenerData);
- if (inner_hashtable.Contains(keyForInnerHashTable_string)) {
- //THIS SHOULD *NEVER* HAPPEN - REMOVE AFTER TESTED WELL
- Debug.Log("TODO (FIX THIS): Event Manager: Listener: " + keyForInnerHashTable_string + " is already in list for event: " + keyForOuterHashTable_string);
- } else {
- // ADD
- inner_hashtable.Add(keyForInnerHashTable_string, eventListenerData);
- wasSuccessful_boolean = true;
- //Debug.Log (" ADDED AT: " + keyForInnerHashTable_string + " = " + eventListenerData);
- }
- }
- return wasSuccessful_boolean;
- }
- /// <summary>
- /// Hases the event listener.
- /// </summary>
- /// <returns>
- /// The event listener.
- /// </returns>
- /// <param name='aIEventListener'>
- /// If set to <c>true</c> a I event listener.
- /// </param>
- /// <param name='aEventName_string'>
- /// If set to <c>true</c> a event name_string.
- /// </param>
- /// <param name='aEventDelegate'>
- /// If set to <c>true</c> a event delegate.
- /// </param>
- public bool hasEventListener(string aEventName_string, EventDelegate aEventDelegate)
- {
- //
- bool hasEventListener_boolean = false;
- //
- object aIEventListener = _getArgumentsCallee(aEventDelegate);
- // OUTER
- string keyForOuterHashTable_string = _getKeyForOuterHashTable (aEventName_string);
- if (_eventListenerDatas_hashtable.ContainsKey(keyForOuterHashTable_string)) {
- // INNER
- Hashtable inner_hashtable = _eventListenerDatas_hashtable[keyForOuterHashTable_string] as Hashtable;
- string keyForInnerHashTable_string = _getKeyForInnerHashTable (new EventListenerData (aIEventListener, aEventName_string, aEventDelegate, EventDispatcherAddMode.DEFAULT));
- //
- if (inner_hashtable.Contains(keyForInnerHashTable_string)) {
- hasEventListener_boolean = true;
- }
- }
- return hasEventListener_boolean;
- }
- /// <summary>
- /// Removes the event listener.
- /// </summary>
- /// <returns>
- /// The event listener.
- /// </returns>
- /// <param name='aIEventListener'>
- /// If set to <c>true</c> a I event listener.
- /// </param>
- /// <param name='aEventName_string'>
- /// If set to <c>true</c> a event name_string.
- /// </param>
- /// <param name='aEventDelegate'>
- /// If set to <c>true</c> a event delegate.
- /// </param>
- public bool removeEventListener(string aEventName_string, EventDelegate aEventDelegate)
- {
- //
- bool wasSuccessful_boolean = false;
- //
- if (hasEventListener (aEventName_string, aEventDelegate)) {
- // OUTER
- string keyForOuterHashTable_string = _getKeyForOuterHashTable (aEventName_string);
- Hashtable inner_hashtable = _eventListenerDatas_hashtable[keyForOuterHashTable_string] as Hashtable;
- //
- object aIEventListener = _getArgumentsCallee(aEventDelegate);
- // INNER
- string keyForInnerHashTable_string = _getKeyForInnerHashTable (new EventListenerData (aIEventListener, aEventName_string, aEventDelegate, EventDispatcherAddMode.DEFAULT));
- inner_hashtable.Remove(keyForInnerHashTable_string);
- wasSuccessful_boolean = true;
- }
- return wasSuccessful_boolean;
- }
- /// <summary>
- /// Removes all event listeners.
- /// </summary>
- /// <returns>
- /// The all event listeners.
- /// </returns>
- public bool removeAllEventListeners()
- {
- //
- bool wasSuccessful_boolean = false;
- //TODO, IS IT A MEMORY LEAK TO JUST RE-CREATE THE TABLE? ARE THE INNER HASHTABLES LEAKING?
- _eventListenerDatas_hashtable = new Hashtable();
- return wasSuccessful_boolean;
- }
- /// <summary>
- /// Dispatchs the event.
- /// </summary>
- /// <returns>
- /// The event.
- /// </returns>
- /// <param name='aIEvent'>
- /// If set to <c>true</c> a I event.
- /// </param>
- public bool dispatchEvent(IEvent aIEvent)
- {
- //
- bool wasSuccessful_boolean = false;
- //
- _doAddTargetValueToIEvent (aIEvent);
- // OUTER
- string keyForOuterHashTable_string = _getKeyForOuterHashTable (aIEvent.type);
- int dispatchedCount_int = 0;
- if (_eventListenerDatas_hashtable.ContainsKey(keyForOuterHashTable_string)) {
- // INNER
- Hashtable inner_hashtable = _eventListenerDatas_hashtable[keyForOuterHashTable_string] as Hashtable;
- IEnumerator innerHashTable_ienumerator = inner_hashtable.GetEnumerator();
- DictionaryEntry dictionaryEntry;
- EventListenerData eventListenerData;
- ArrayList toBeRemoved_arraylist = new ArrayList ();
- //
- while (innerHashTable_ienumerator.MoveNext()) {
- dictionaryEntry = (DictionaryEntry)innerHashTable_ienumerator.Current;
- eventListenerData = dictionaryEntry.Value as EventListenerData;
- //***DO THE DISPATCH***
- //Debug.Log ("DISPATCH : ");
- //Debug.Log (" n : " + eventListenerData.eventName );
- //Debug.Log (" from : " + aIEvent.target );
- //Debug.Log (" to : " + eventListenerData.eventListener );
- //Debug.Log (" del : " + eventListenerData.eventDelegate + " " + (eventListenerData.eventDelegate as System.Delegate).Method.DeclaringType.Name + " " + (eventListenerData.eventDelegate as System.Delegate).Method.Name.ToString());
- eventListenerData.eventDelegate (aIEvent);
- //TODO - THIS IS PROBABLY FUNCTIONAL BUT NOT OPTIMIZED, MY APPROACH TO HOW/WHY SINGLE SHOTS ARE REMOVED
- //REMOVE IF ONESHOT
- if (eventListenerData.eventListeningMode == EventDispatcherAddMode.SINGLE_SHOT) {
- toBeRemoved_arraylist.Add (eventListenerData);
- }
- //MARK SUCCESS, BUT ALSO CONTINUE LOOPING TOO
- wasSuccessful_boolean = true;
- dispatchedCount_int++;
- }
- //CLEANUP ANY ONE-SHOT, SINGLE-USE
- EventListenerData toBeRemoved_eventlistenerdata;
- for (int count_int = toBeRemoved_arraylist.Count -1; count_int >= 0; count_int --) {
- toBeRemoved_eventlistenerdata = toBeRemoved_arraylist[count_int] as EventListenerData;
- removeEventListener (toBeRemoved_eventlistenerdata.eventName, toBeRemoved_eventlistenerdata.eventDelegate);
- }
- }
- return wasSuccessful_boolean;
- }
- /// <summary>
- /// _dos the add target value to I event.
- /// </summary>
- /// <param name='aIEvent'>
- /// A I event.
- /// </param>
- /// <exception cref='System.NotImplementedException'>
- /// Is thrown when a requested operation is not implemented for a given type.
- /// </exception>
- public void _doAddTargetValueToIEvent (IEvent aIEvent)
- {
- aIEvent.target = _target_object;
- }
- public void OnApplicationQuit()
- {
- //TODO, DO THIS CLEANUP HERE, OR OBLIGATE API-USER TO DO IT??
- _eventListenerDatas_hashtable.Clear();
- }
- private string _getKeyForOuterHashTable (string aEventName_string)
- {
- //SIMPLY USING THE EVENT NAME - METHOD USED HERE, IN CASE I WANT TO TWEAK THIS MORE...
- return aEventName_string;
- }
- private string _getKeyForInnerHashTable (EventListenerData aEventListenerData)
- {
- //VERY UNIQUE - NICE!
- return aEventListenerData.eventListener.GetType().FullName + "_" + aEventListenerData.eventListener.GetType().GUID + "_" + aEventListenerData.eventName + "_" + (aEventListenerData.eventDelegate as System.Delegate).Method.Name.ToString();
- }
- public object _getArgumentsCallee (EventDelegate aEventDelegate)
- {
- return (aEventDelegate as System.Delegate).Target;
- }
- }
- }
- namespace EventDispatcher
- {
- /// <summary>
- /// EventListenerData
- /// </summary>
- public class EventListenerData
- {
- /// <summary>
- /// The _event listener.
- /// </summary>
- private object _eventListener;
- public object eventListener
- {
- get
- {
- return _eventListener;
- }
- set
- {
- _eventListener = value;
- }
- }
- /// <summary>
- /// 事件名
- /// </summary>
- private string _eventName_string;
- public string eventName
- {
- get
- {
- return _eventName_string;
- }
- set
- {
- _eventName_string = value;
- }
- }
- /// <summary>
- /// 事件委托
- /// </summary>
- private EventDelegate _eventDelegate;
- public EventDelegate eventDelegate
- {
- get
- {
- return _eventDelegate;
- }
- set
- {
- _eventDelegate = value;
- }
- }
- private EventDispatcherAddMode _eventListeningMode;
- public EventDispatcherAddMode eventListeningMode
- {
- get
- {
- return _eventListeningMode;
- }
- set
- {
- _eventListeningMode = value;
- }
- }
- ///<summary>
- /// Constructor
- ///</summary>
- public EventListenerData (object aEventListener, string aEventName_string, EventDelegate aEventDelegate, EventDispatcherAddMode aEventListeningMode )
- {
- _eventListener = aEventListener;
- _eventName_string = aEventName_string;
- _eventDelegate = aEventDelegate;
- _eventListeningMode = aEventListeningMode;
- }
- /// <summary>
- /// Deconstructor
- /// </summary>
- //~EventListenerData ( )
- //{
- //Debug.Log ("EventListenerData.deconstructor()");
- //}
- }
- }
使用的例子:新建两个游戏对象然后挂上脚本!
- namespace EventDispatcher
- {
- /// <summary>
- /// Test event.
- /// </summary>
- public class SampleEvent : Event
- {
- // GETTER / SETTER
- /// <summary>
- /// An example of event-specific data you can add in.
- /// </summary>
- private string _customValue_string;
- public string customValue
- {
- get {
- return _customValue_string;
- }
- set {
- _customValue_string = value;
- }
- }
- /// <summary>
- /// The Event Type Name
- /// </summary>
- public static string SAMPLE_EVENT = "SAMPLE_EVENT";
- /// <summary>
- /// Initializes a new instance of the <see cref="com.rmc.projects.event_dispatcher.SampleEvent"/> class.
- /// </summary>
- /// <param name="aType_str">A type_str.</param>
- public SampleEvent (string aType_str ) : base (aType_str)
- {
- }
- /// <summary>
- /// Releases unmanaged resources and performs other cleanup operations before the
- /// <see cref="com.rmc.projects.event_dispatcher.SampleEvent"/> is reclaimed by garbage collection.
- /// </summary>
- //~SampleEvent ( )
- //{
- // Debug.Log ("SampleEvent.deconstructor()");
- //}
- }
- }
- using UnityEngine;
- namespace EventDispatcher
- {
- public class SampleObservedComponent : MonoBehaviour
- {
- /// <summary>
- /// The event dispatcher.
- /// </summary>
- public EventDispatcher eventDispatcher;
- /// <summary>
- /// Initializes a new instance of the <see cref="com.rmc.projects.event_dispatcher.SampleObservedComponent"/> class.
- /// </summary>
- public SampleObservedComponent ()
- {
- eventDispatcher = new EventDispatcher (this);
- }
- ///<summary>
- /// Use this for initialization
- ///</summary>
- public void Start ()
- {
- SampleEvent sampleEvent = new SampleEvent (SampleEvent.SAMPLE_EVENT);
- sampleEvent.customValue = "foo";
- Debug.Log ("Dispatching: SampleEvent " + sampleEvent);
- eventDispatcher.dispatchEvent (sampleEvent);
- }
- /// <summary>
- /// Raises the destroy event.
- /// </summary>
- public void OnDestroy ()
- {
- // CLEANUP MEMORY
- eventDispatcher.removeAllEventListeners();
- eventDispatcher = null;
- }
- }
- }
- using UnityEngine;
- namespace EventDispatcher
- {
- public class SampleObserverComponent : MonoBehaviour
- {
- /// <summary>
- /// The sample observed game object.
- /// </summary>
- public SampleObservedComponent sampleObservedGameObject;
- public void Start ()
- {
- /*
- * 注意: 这里observer和observed是 MonoBehavior 子类
- **/
- sampleObservedGameObject.eventDispatcher.addEventListener (SampleEvent.SAMPLE_EVENT, _onSampleEvent);
- }
- void Update ()
- {
- //Debug.Log (sampleObservedGameObject.eventDispatcher);
- }
- /// <summary>
- /// Raises the destroy event.
- /// </summary>
- public void OnDestroy ()
- {
- // CLEANUP MEMORY
- sampleObservedGameObject.eventDispatcher.removeEventListener (SampleEvent.SAMPLE_EVENT, _onSampleEvent);
- }
- //--------------------------------------
- // Events
- //--------------------------------------
- /// <summary>
- /// _ons the sample event.
- /// </summary>
- /// <param name="aIEvent">A I event.</param>
- public void _onSampleEvent (IEvent aIEvent)
- {
- Debug.Log ("\tListening: _onSampleEvent() aIEvent: " + aIEvent + " with customValue: " + (aIEvent as SampleEvent).customValue);
- }
- }
- }