我一直都有一個需求,就是可以很方便的將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);
發送消息的函數大概這樣的:
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