【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

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