我一直都有一个需求,就是可以很方便的将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