首页 > Windows开发 > 详细

C#消息事件封装

时间:2017-03-04 22:47:05      阅读:363      评论:0      收藏:0      [点我收藏+]

本人一直认为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移除了事件,所以第二次不会触发。

这只是部分大码。详细请见附件。

本文出自 “Better_Power_Wisdom” 博客,请务必保留此出处http://aonaufly.blog.51cto.com/3554853/1903256

C#消息事件封装

原文:http://aonaufly.blog.51cto.com/3554853/1903256

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!