【Unity&C#】寫了一個事件分發器

我一直都有一個需求,就是可以很方便的將Socket傳進來的二進制解析到具體的某個消息,每個消息都有自己的事件處理。之前有寫過一個這樣的,但是事件處理必須寫在各個消息類裏面,這樣不是很好。現在藉着C#的泛型協變的這個特性,做了一個強類型的事件分發器。


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FirBase
{
    class CDispatcherHelper
    {
        public static string GetKey<T>()
        {
            Type t = typeof(T);
            return t.Name;
        }
    }
    public interface ICallback<out T>
    {
        T GetData(byte[] data);
        void Exce(byte[] data);
    }

    public class CallBack<T> : ICallback<T>
    {
        private Action<T> _handle = null;

        public CallBack(Action<T> handle)
        {
            _handle = handle;
        }

        public void Exce(byte[] data)
        {
            var tData = GetData(data);
            exce(tData);
        }

        public T GetData(byte[] data)
        {
            return SerializationHelper.BinaryDeSerialization<T>(data);
        }

        public void exce(T data)
        {
            if (_handle != null)
            {
                _handle(data);
            } 
        }
    }

    public class Dispatcher
    {
        private Dictionary<string, ICallback<Object>> _callBackDic = new Dictionary<string, ICallback<Object>>();
        private ICallback<Object> _curCallBack = null;

        /// <summary>
        /// 註冊消息
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="callback"></param>
        /// <returns></returns>
        public bool Reg<T>(ICallback<T> callback)
        {
            _callBackDic[CDispatcherHelper.GetKey<T>()] = (ICallback<Object>)callback;
            return false;
        }

        /// <summary>
        /// 分發消息
        /// </summary>
        /// <param name="key"></param>
        /// <param name="data"></param>
        public void MsgDispatcher(string key, byte[] data)
        {
            if (_callBackDic.TryGetValue(key, out _curCallBack))
            {
                _curCallBack.Exce(data);
            }
        }
    }
}

沒有做多線程的處理

現在是例子,首先我們定義一個TestMsg,這個類必須是可序列化的。

    [Serializable]
    class TestMsg
    {
        public string aa;
        public string bb;
    }

然後我們要註冊消息,並且設置消息的回調函數

    class MsgHandle
    {
        public MsgHandle(FirBase.Dispatcher dispatcher)
        {
            dispatcher.Reg(new FirBase.CallBack<TestMsg>(OnTestMsg));
        }

        public void OnTestMsg(TestMsg msg)
        {
            FirBase.FirLog.v(this, "aa=" + msg.aa + "bb=" + msg.bb);
        }
    }

然後在main函數中這樣調用

            Dispatcher testDispatcher = new Dispatcher();
            MsgHandle handle = new MsgHandle(testDispatcher);


接下來,我們6秒後發送消息,這就需要用到之前造的輪子協程了。

發送消息的函數大概這樣的:

        private static IEnumerator delaySendMsg(Dispatcher dispatcher)
        {
            yield return new FirBase.WaitForSecond(new TimeSpan(0, 0, 6));
            TestMsg msg = new TestMsg();
            msg.aa = "haha";
            msg.bb = "heihei";
            dispatcher.MsgDispatcher(DispatcherHelper.GetKey<TestMsg>(), SerializationHelper.BinarySerialization(msg));
        }

然後協程的調用是這樣的:

            FirTask.Instance.AddTask(delaySendMsg(testDispatcher));
            
            while(true)
            {
                FirTask.Instance.DoTask();
            }

運行結果如下:




最後的最後,忘了說序列化那塊了,調用的是C#自帶的序列化函數,只是稍微包裝了一下:

    public class SerializationHelper
    {
        /// <summary>
        /// 二進制序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        public static byte[] BinarySerialization<T>(T data)
        {
            byte[] bData = null;
            BinaryFormatter formatter = new BinaryFormatter();
            using (MemoryStream stream = new MemoryStream())
            {
                formatter.Serialize(stream, data);
                bData = stream.GetBuffer();
            }
            return bData;
        }

        /// <summary>
        /// 二進制反序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        public static T BinaryDeSerialization<T>(byte[] data)
        {
            T t;
            BinaryFormatter formatter = new BinaryFormatter();
            using (MemoryStream stream = new MemoryStream(data))
            {
                t = (T)formatter.Deserialize(stream);
            }
            return t;
        }
    }


demo在這裏,這篇博客一最後

http://blog.csdn.net/nxshow/article/details/51067764

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章