110,533
社区成员
发帖
与我相关
我的任务
分享
#region -方法
/// <summary>
/// 序列化TcpMessage对象
/// </summary>
/// <param name="Msg"></param>
/// <returns></returns>
// 采用二进制序列化取代了XML序列化,二进制体积小,速度快,但是有一定的限定条件
public static byte[] GetMessageByte_(TcpMsg Msg)
{
using (MemoryStream memStream = new MemoryStream())
{
BinaryFormatter brFormatter = new BinaryFormatter();
brFormatter.Serialize(memStream, Msg);
return memStream.ToArray();
//XmlSerializer xs = new XmlSerializer(typeof(TcpMsg));
//xs.Serialize(memStream, Msg);
//return memStream.ToArray();
}
}
/// <summary>
/// 反序列化TcpMessage对象
/// </summary>
/// <param name="Msg"></param>
/// <returns></returns>
// 采用二进制序列化取代了XML序列化,二进制体积小,速度快,但是有一定的限定条件
public static TcpMsg GetMessage_(byte[] Msg)
{
try
{
using (MemoryStream memStream = new MemoryStream(Msg))
{
BinaryFormatter brFormatter = new BinaryFormatter();
// 此接口可以强制转换反序列化程序集的名称信息。
brFormatter.Binder = new ConvertAssemblyBinder();
TcpMsg tm = (TcpMsg)brFormatter.Deserialize(memStream);
//XmlSerializer xs = new XmlSerializer(typeof(TcpMsg));
//TcpMsg tm = xs.Deserialize(memStream) as TcpMsg;
return tm;
}
}
catch (Exception)
{
return null;
}
}
/// <summary>
/// 序列化CSFTcpMsg对象,并附加前缀包大小
/// </summary>
/// <param name="Msg"></param>
/// <returns></returns>
public static byte[] GetMessageByteEx(TcpMsg Msg)
{
byte[] MsgData = TcpMsg.GetMessageByte_(Msg);
byte[] sendData = new byte[4 + MsgData.Length];
byte[] DataLeg = BitConverter.GetBytes(MsgData.Length);
Array.Copy(DataLeg, 0, sendData, 0, DataLeg.Length);
Array.Copy(MsgData, 0, sendData, DataLeg.Length, MsgData.Length);
return sendData;
}
/// <summary>
/// 反序列化带有大小前缀的byte数组到CSFTcpMsg对象数组(可能是一个对象,也可能是多个)
/// </summary>
/// <param name="Msg"></param>
/// <returns></returns>
public static TcpMsg[] GetMessageEx(byte[] Msg)
{
try
{
List<TcpMsg> list = new List<TcpMsg>();
byte[] CSFData = null;
int nPosition = 0;
while (nPosition < Msg.Length)
{
// 读取数据头的包大小
CSFData = new byte[BitConverter.ToInt32(Msg, nPosition)];
nPosition += 4;
// 读取包数据
Array.Copy(Msg, nPosition, CSFData, 0, CSFData.Length);
nPosition += CSFData.Length;
TcpMsg CSFmsg = TcpMsg.GetMessage_(CSFData);
if (CSFmsg != null)
{
list.Add(CSFmsg);
}
else
{
return null;
}
}
return list.ToArray();
}
catch (Exception)
{
return null;
}
}
/// <summary>
/// 转换Base64到文本
/// </summary>
/// <param name="Data"></param>
/// <returns></returns>
public static string GetText(byte[] Data)
{
return System.Text.Encoding.ASCII.GetString(Data);
}
/// <summary>
/// 转换文本到Base64
/// </summary>
/// <param name="Data"></param>
/// <returns></returns>
public static byte[] GetBase64(string Data)
{
return System.Text.Encoding.ASCII.GetBytes(Data);
}
#endregion
#region -控制将序列化对象绑定到类型的过程
/// <summary>
/// 控制将序列化对象绑定到类型的过程
/// </summary>
public sealed class ConvertAssemblyBinder : SerializationBinder
{
/// <summary>
/// 控制二进制序列化类型转换
/// </summary>
/// <param name="assemblyName"></param>
/// <param name="typeName"></param>
/// <returns></returns>
// 在序列化过程中,格式化程序传输创建正确类型和版本的对象的实例所需的信息。
// 此信息通常包括对象的完整类型名称和程序集名称。
// 程序集名称包含程序集的名称、版本和强名称(请参见具有强名称的程序集)散列。
// 默认情况下,反序列化将使用此信息创建等同对象的实例(安全策略所限制的任何程序集加载属于例外)。
// 因为类已经在程序集之间移动或者因为在服务器和客户端上要求类的不同版本,有些用户需要控制要加载哪些类。
// 这是一个抽象基类。所有联编程序都扩展此类。
// 给继承者的说明 从 SerializationBinder 继承时,必须重写以下成员:BindToType。
// 由于服务器和客户端共同使用同一个类型,进行数据传递,但是服务器和客户端的同一类型处于不同的
// 程序集,需要在反序列化的时候,提供强制类型转换
public override Type BindToType(string assemblyName, string typeName)
{
// 取得当前的程序集名称,取得传递过来,类型名称不修改,都是"TestPro.CSFTcpMsg"
string strCurAssembly = Assembly.GetExecutingAssembly().FullName;
// 返回当前对应的类型
Type CurType = Type.GetType(String.Format("{0}, {1}", typeName, strCurAssembly));
return CurType;
}
}
#endregion