本人一直认为AS3的事件处理机制很是给力 , 今天鼓捣了出来并完美得通过了测试。在AS3中使用函数addEventListener添加事件侦听,用removeEventListener移除事件侦听。着用封装的一个类库可以彻底地终结消息传递中无规则,无规律的混乱状态,从而达到代码逻辑清晰性。改起来也相当简单(做过程序员的都懂)。
关于此类库的实现原理 , 其实使用的是委托(delegate),让侦听函数(观察者)挂载到此委托上,当然消息有不同的类型,如windows系统中有单击,双击,右击等不同的事件类型,在这个类库里面都有实现。
首先,需要指出:
IEventType ( 所有事件类型的接口 )
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MsgEventLib.com
{
public interface IEventType
{
/// <summary>
/// 类的类型
/// </summary>
Type EventMainType { get; }
String GetEventTypeName(string type);
}
}
思想:事件类型以 类的Type.Name + "_" + 事件名称 。 以GetEventTypeName方法实现。
传递的消息体:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MsgEventLib.com
{
public class BaseEvent
{
public BaseEvent(string eventType, object sender, object msg)
{
this.eventType = eventType;
this.sender = sender;
this.msg = msg;
}
private string @eventType;
public string EventType
{
set { this.eventType = value; }
get { return this.eventType; }
}
private object @sender;
public Object Sender
{
set { this.sender = value; }
get { return this.sender; }
}
private object @msg;
public object Msg
{
set { this.msg = value; }
get { return this.msg; }
}
}
}
其中:eventType为事件类型名称 GetEventTypeName , Sender为发送者 , Msg为消息体
事件侦听管理器的实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MsgEventLib.com
{
public sealed class EventListener : IEventListener
{
private static IEventListener @instance;
public static IEventListener Instance
{
get {
if (instance == null) instance = new EventListener();
return instance;
}
}
private Dictionary<string, DeListener> @listeners;
private EventListener()
{
@listeners = new Dictionary<string, DeListener>();
}
public void AddEventListener(string type, DeListener myListener)
{
if (!@listeners.ContainsKey(type))
@listeners.Add(type, myListener);
else
@listeners[type] += myListener;
}
public void RemoveEventListener(string type, DeListener myListener)
{
if (@listeners.ContainsKey(type))
{
@listeners[type] -= myListener;
if (@listeners[type] == null)
@listeners.Remove(type);
}
}
public void RemoveAllEventListener()
{
if (@listeners != null && @listeners.Count > 0)
{
List<string> keys = new List<string>(@listeners.Keys);//获得所有的键值
for (int j = 0; j < keys.Count; j++)
{
if (@listeners[keys[j]] != null)
{
Delegate[] des = @listeners[keys[j]].GetInvocationList();
if (des != null && des.Length > 0)
{
for (int i = 0; i < des.Length; i++)
{
@listeners[keys[j]] -= des[i] as DeListener;
}
}
}
@listeners.Remove(keys[j]);
}
}
}
public DeListener GetDeListenerByType(string type)
{
if (@listeners != null && @listeners.ContainsKey(type))
{
return @listeners[type];
}
return null;
}
public void Destory()
{
this.RemoveAllEventListener();
if (@instance != null) @instance = null;
}
}
}
值得注意的是 , 字典 : key为事件类型(GetEventTypeName) , value为委托(可能有多个挂载/观察者)
关于事件发送者(主题)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MsgEventLib.com
{
public sealed class EventDispacterManager : IEventDispacterManager
{
private static IEventDispacterManager @instance;
public static IEventDispacterManager Instance
{
get
{
if (instance == null) instance = new EventDispacterManager();
return instance;
}
}
public void Dispatch(string type , BaseEvent @myevent)
{
DeListener target = EventListener.Instance.GetDeListenerByType(type);
if (target != null)
{
target(@myevent);
}
}
}
}
测试的结果
1 , 事件类型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MsgEventLib.com;
namespace TestA.com
{
public class MyEventType : IEventType
{
private static MyEventType @instance;
public static MyEventType Instance
{
get {
if (@instance == null) @instance = new MyEventType();
return @instance;
}
}
public Type EventMainType
{
get { return typeof(MyEventType); }
}
public string GetEventTypeName(string type)
{
return this.EventMainType.Name + "_" + type;
}
public static string CLOSE_WINDOWS = "CLOSE_WINDOWS";
public static string OTHRT_TYPE = "OTHRT_TYPE";
}
}
2 , 3个类(侦听着)
①:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MsgEventLib.com;
namespace TestA.com
{
public sealed class Listeners
{
public Listeners()
{
string type = MyEventType.Instance.GetEventTypeName(MyEventType.CLOSE_WINDOWS);
EventListener.Instance.AddEventListener(type, this.Li);
}
private void Li(BaseEvent e)
{
Console.WriteLine("Listeners 触发了Event {0} ", e.Msg);
}
}
}
②:
using MsgEventLib.com;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestA.com
{
public sealed class Lis2
{
public Lis2()
{
string type = MyEventType.Instance.GetEventTypeName(MyEventType.CLOSE_WINDOWS);
EventListener.Instance.AddEventListener(type, this.Li);
}
private void Li(BaseEvent e)
{
Console.WriteLine("Lis2 触发了Event {0} ", e.Msg);
}
public void RemoveLis()
{
string type = MyEventType.Instance.GetEventTypeName(MyEventType.CLOSE_WINDOWS);
EventListener.Instance.RemoveEventListener(type, this.Li);
Console.WriteLine("Lis2 移除了事件侦听!");
}
}
}
③:
using MsgEventLib.com;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestA.com
{
public sealed class Lis3
{
public Lis3()
{
string type = MyEventType.Instance.GetEventTypeName(MyEventType.OTHRT_TYPE);
EventListener.Instance.AddEventListener(type, this.Li);
}
private void Li(BaseEvent e)
{
Console.WriteLine("Lis3 触发了Event {0} ", e.Msg);
}
}
}
事件发送者
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MsgEventLib.com;
namespace TestA.com
{
public sealed class Dispatch
{
public void Dis()
{
string type = MyEventType.Instance.GetEventTypeName(MyEventType.CLOSE_WINDOWS);
EventDispacterManager.Instance.Dispatch(type,
new BaseEvent(type, this, "Event_关闭你的窗口"));
}
}
}
测试:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TestA.com;
namespace TestA
{
public class Program
{
static void Main(string[] args)
{
Dispatch di = new Dispatch();
Listeners li = new Listeners();
Lis2 li2 = new Lis2();
Lis3 li3 = new Lis3();
di.Dis();
li2.RemoveLis();
di.Dis();
Console.Read();
}
}
}
结果:
因为Lis3侦听的不是事件CLOSE_WINDOWS , 既不会触发 。 因为Lis2移除了事件,所以第二次不会触发。
这只是部分大码。详细请见附件。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。