You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
675 lines
28 KiB
675 lines
28 KiB
|
3 months ago
|
//------------------------------------------------------------------------------
|
||
|
|
// 此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有
|
||
|
|
// 源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
|
||
|
|
// CSDN博客:https://blog.csdn.net/qq_40374647
|
||
|
|
// 哔哩哔哩视频:https://space.bilibili.com/94253567
|
||
|
|
// Gitee源代码仓库:https://gitee.com/RRQM_Home
|
||
|
|
// Github源代码仓库:https://github.com/RRQM
|
||
|
|
// API首页:https://www.yuque.com/rrqm/touchsocket/index
|
||
|
|
// 交流QQ群:234762506
|
||
|
|
// 感谢您的下载和使用
|
||
|
|
//------------------------------------------------------------------------------
|
||
|
|
//------------------------------------------------------------------------------
|
||
|
|
using System;
|
||
|
|
using System.Collections;
|
||
|
|
using System.Collections.Concurrent;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.Data;
|
||
|
|
using System.Reflection;
|
||
|
|
using System.Text;
|
||
|
|
|
||
|
|
namespace TouchSocket.Core
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// 快速二进制序列化。
|
||
|
|
/// </summary>
|
||
|
|
public static class FastBinaryFormatter
|
||
|
|
{
|
||
|
|
static FastBinaryFormatter()
|
||
|
|
{
|
||
|
|
AddFastBinaryConverter<Version, VersionFastBinaryConverter>();
|
||
|
|
}
|
||
|
|
private static readonly ConcurrentDictionary<Type, SerializObject> m_instanceCache = new ConcurrentDictionary<Type, SerializObject>();
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 添加转换器。
|
||
|
|
/// </summary>
|
||
|
|
public static void AddFastBinaryConverter<TType, TConverter>() where TConverter : IFastBinaryConverter, new()
|
||
|
|
{
|
||
|
|
AddFastBinaryConverter(typeof(TType), (IFastBinaryConverter)Activator.CreateInstance(typeof(TConverter)));
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 添加转换器。
|
||
|
|
/// </summary>
|
||
|
|
/// <typeparam name="TType"></typeparam>
|
||
|
|
/// <param name="converter"></param>
|
||
|
|
public static void AddFastBinaryConverter<TType>(IFastBinaryConverter converter)
|
||
|
|
{
|
||
|
|
AddFastBinaryConverter(typeof(TType), converter);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 添加转换器。
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="type"></param>
|
||
|
|
/// <param name="converter"></param>
|
||
|
|
public static void AddFastBinaryConverter(Type type, IFastBinaryConverter converter)
|
||
|
|
{
|
||
|
|
m_instanceCache.AddOrUpdate(type, new SerializObject(type) { Converter = converter }, (k, v) => v);
|
||
|
|
}
|
||
|
|
|
||
|
|
#region Serialize
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 序列化对象
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="byteBlock">流</param>
|
||
|
|
/// <param name="graph">对象</param>
|
||
|
|
public static void Serialize<T>(ByteBlock byteBlock, T graph)
|
||
|
|
{
|
||
|
|
byteBlock.Position = 1;
|
||
|
|
SerializeObject(byteBlock, graph);
|
||
|
|
byteBlock.Buffer[0] = 1;
|
||
|
|
byteBlock.SetLength(byteBlock.Position);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static int SerializeClass<T>(ByteBlock stream, T obj, Type type)
|
||
|
|
{
|
||
|
|
int len = 0;
|
||
|
|
if (obj != null)
|
||
|
|
{
|
||
|
|
SerializObject serializObject = GetOrAddInstance(type);
|
||
|
|
|
||
|
|
for (int i = 0; i < serializObject.MemberInfos.Length; i++)
|
||
|
|
{
|
||
|
|
MemberInfo memberInfo = serializObject.MemberInfos[i];
|
||
|
|
byte[] propertyBytes = Encoding.UTF8.GetBytes(memberInfo.Name);
|
||
|
|
if (propertyBytes.Length > byte.MaxValue)
|
||
|
|
{
|
||
|
|
throw new Exception($"属性名:{memberInfo.Name}超长");
|
||
|
|
}
|
||
|
|
stream.Write((byte)propertyBytes.Length);
|
||
|
|
stream.Write(propertyBytes, 0, propertyBytes.Length);
|
||
|
|
len += propertyBytes.Length + 1;
|
||
|
|
//len += SerializeObject(stream, property.GetValue(obj));
|
||
|
|
len += SerializeObject(stream, serializObject.MemberAccessor.GetValue(obj, memberInfo.Name));
|
||
|
|
}
|
||
|
|
//foreach (PropertyInfo property in serializObject.Properties)
|
||
|
|
//{
|
||
|
|
//}
|
||
|
|
|
||
|
|
//foreach (FieldInfo fieldInfo in serializObject.FieldInfos)
|
||
|
|
//{
|
||
|
|
// byte[] propertyBytes = Encoding.UTF8.GetBytes(fieldInfo.Name);
|
||
|
|
// if (propertyBytes.Length > byte.MaxValue)
|
||
|
|
// {
|
||
|
|
// throw new Exception($"属性名:{fieldInfo.Name}超长");
|
||
|
|
// }
|
||
|
|
// byte lenBytes = (byte)propertyBytes.Length;
|
||
|
|
// stream.Write(lenBytes);
|
||
|
|
// stream.Write(propertyBytes, 0, propertyBytes.Length);
|
||
|
|
// len += propertyBytes.Length + 1;
|
||
|
|
// len += SerializeObject(stream, fieldInfo.GetValue(obj));
|
||
|
|
//}
|
||
|
|
}
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static int SerializeDictionary(ByteBlock stream, IEnumerable param)
|
||
|
|
{
|
||
|
|
int len = 0;
|
||
|
|
if (param != null)
|
||
|
|
{
|
||
|
|
long oldPosition = stream.Position;
|
||
|
|
stream.Position += 4;
|
||
|
|
len += 4;
|
||
|
|
uint paramLen = 0;
|
||
|
|
|
||
|
|
foreach (dynamic item in param)
|
||
|
|
{
|
||
|
|
len += SerializeObject(stream, item.Key);
|
||
|
|
len += SerializeObject(stream, item.Value);
|
||
|
|
paramLen++;
|
||
|
|
}
|
||
|
|
long newPosition = stream.Position;
|
||
|
|
stream.Position = oldPosition;
|
||
|
|
stream.Write(TouchSocketBitConverter.Default.GetBytes(paramLen));
|
||
|
|
stream.Position = newPosition;
|
||
|
|
}
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static int SerializeIListOrArray(ByteBlock stream, IEnumerable param)
|
||
|
|
{
|
||
|
|
int len = 0;
|
||
|
|
if (param != null)
|
||
|
|
{
|
||
|
|
long oldPosition = stream.Position;
|
||
|
|
stream.Position += 4;
|
||
|
|
len += 4;
|
||
|
|
uint paramLen = 0;
|
||
|
|
|
||
|
|
foreach (object item in param)
|
||
|
|
{
|
||
|
|
paramLen++;
|
||
|
|
len += SerializeObject(stream, item);
|
||
|
|
}
|
||
|
|
long newPosition = stream.Position;
|
||
|
|
stream.Position = oldPosition;
|
||
|
|
stream.Write(TouchSocketBitConverter.Default.GetBytes(paramLen));
|
||
|
|
stream.Position = newPosition;
|
||
|
|
}
|
||
|
|
return len;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static int SerializeObject<T>(ByteBlock byteBlock, T graph)
|
||
|
|
{
|
||
|
|
int len = 0;
|
||
|
|
byte[] data = null;
|
||
|
|
|
||
|
|
long startPosition = byteBlock.Position;
|
||
|
|
long endPosition;
|
||
|
|
if (graph != null)
|
||
|
|
{
|
||
|
|
Type type = graph.GetType();
|
||
|
|
if (type.IsPrimitive)
|
||
|
|
{
|
||
|
|
switch (graph)
|
||
|
|
{
|
||
|
|
case byte value:
|
||
|
|
{
|
||
|
|
data = new byte[] { value };
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case sbyte value:
|
||
|
|
{
|
||
|
|
data = TouchSocketBitConverter.Default.GetBytes(value);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case bool value:
|
||
|
|
{
|
||
|
|
data = TouchSocketBitConverter.Default.GetBytes(value);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case short value:
|
||
|
|
{
|
||
|
|
data = TouchSocketBitConverter.Default.GetBytes(value);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case ushort value:
|
||
|
|
{
|
||
|
|
data = TouchSocketBitConverter.Default.GetBytes(value);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case int value:
|
||
|
|
{
|
||
|
|
data = TouchSocketBitConverter.Default.GetBytes(value);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case uint value:
|
||
|
|
{
|
||
|
|
data = TouchSocketBitConverter.Default.GetBytes(value);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case long value:
|
||
|
|
{
|
||
|
|
data = TouchSocketBitConverter.Default.GetBytes(value);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case ulong value:
|
||
|
|
{
|
||
|
|
data = TouchSocketBitConverter.Default.GetBytes(value);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case float value:
|
||
|
|
{
|
||
|
|
data = TouchSocketBitConverter.Default.GetBytes(value);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case double value:
|
||
|
|
{
|
||
|
|
data = TouchSocketBitConverter.Default.GetBytes(value);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case char value:
|
||
|
|
{
|
||
|
|
data = TouchSocketBitConverter.Default.GetBytes(value);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
{
|
||
|
|
throw new Exception("未知基础类型");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
switch (graph)
|
||
|
|
{
|
||
|
|
case string value:
|
||
|
|
{
|
||
|
|
data = Encoding.UTF8.GetBytes(value);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case DateTime value:
|
||
|
|
{
|
||
|
|
data = TouchSocketBitConverter.Default.GetBytes(value.Ticks);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case Enum _:
|
||
|
|
{
|
||
|
|
var enumValType = Enum.GetUnderlyingType(type);
|
||
|
|
|
||
|
|
if (enumValType == TouchSocketCoreUtility.byteType)
|
||
|
|
{
|
||
|
|
data = new byte[] { Convert.ToByte(graph) };
|
||
|
|
}
|
||
|
|
else if (enumValType == TouchSocketCoreUtility.shortType)
|
||
|
|
{
|
||
|
|
data = TouchSocketBitConverter.Default.GetBytes(Convert.ToInt16(graph));
|
||
|
|
}
|
||
|
|
else if (enumValType == TouchSocketCoreUtility.intType)
|
||
|
|
{
|
||
|
|
data = TouchSocketBitConverter.Default.GetBytes(Convert.ToInt32(graph));
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
data = TouchSocketBitConverter.Default.GetBytes(Convert.ToInt64(graph));
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case byte[] value:
|
||
|
|
{
|
||
|
|
data = value;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
{
|
||
|
|
byteBlock.Position += 4;
|
||
|
|
var serializeObj = GetOrAddInstance(type);
|
||
|
|
if (serializeObj.Converter != null)
|
||
|
|
{
|
||
|
|
len += serializeObj.Converter.Write(byteBlock, graph);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
switch (serializeObj.InstanceType)
|
||
|
|
{
|
||
|
|
case InstanceType.List:
|
||
|
|
len += SerializeIListOrArray(byteBlock, (IEnumerable)graph);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case InstanceType.Array:
|
||
|
|
len += SerializeIListOrArray(byteBlock, (IEnumerable)graph);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case InstanceType.Dictionary:
|
||
|
|
len += SerializeDictionary(byteBlock, (IEnumerable)graph);
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
case InstanceType.Class:
|
||
|
|
len += SerializeClass(byteBlock, graph, type);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (data != null)
|
||
|
|
{
|
||
|
|
len = data.Length;
|
||
|
|
endPosition = len + startPosition + 4;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
endPosition = byteBlock.Position;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
endPosition = startPosition + 4;
|
||
|
|
}
|
||
|
|
|
||
|
|
byte[] lenBuffer = TouchSocketBitConverter.Default.GetBytes(len);
|
||
|
|
byteBlock.Position = startPosition;
|
||
|
|
byteBlock.Write(lenBuffer, 0, lenBuffer.Length);
|
||
|
|
|
||
|
|
if (data != null)
|
||
|
|
{
|
||
|
|
byteBlock.Write(data, 0, data.Length);
|
||
|
|
}
|
||
|
|
byteBlock.Position = endPosition;
|
||
|
|
return len + 4;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion Serialize
|
||
|
|
|
||
|
|
#region Deserialize
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 反序列化
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="data"></param>
|
||
|
|
/// <param name="offset"></param>
|
||
|
|
/// <param name="type"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
public static object Deserialize(byte[] data, int offset, Type type)
|
||
|
|
{
|
||
|
|
if (data[offset] != 1)
|
||
|
|
{
|
||
|
|
throw new Exception("Fast反序列化数据流解析错误。");
|
||
|
|
}
|
||
|
|
offset += 1;
|
||
|
|
return Deserialize(type, data, ref offset);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static object Deserialize(Type type, byte[] datas, ref int offset)
|
||
|
|
{
|
||
|
|
bool nullable = type.IsNullableType();
|
||
|
|
if (nullable)
|
||
|
|
{
|
||
|
|
type = type.GenericTypeArguments[0];
|
||
|
|
}
|
||
|
|
dynamic obj;
|
||
|
|
int len = TouchSocketBitConverter.Default.ToInt32(datas, offset);
|
||
|
|
offset += 4;
|
||
|
|
if (len > 0)
|
||
|
|
{
|
||
|
|
if (type == TouchSocketCoreUtility.stringType)
|
||
|
|
{
|
||
|
|
obj = Encoding.UTF8.GetString(datas, offset, len);
|
||
|
|
}
|
||
|
|
else if (type == TouchSocketCoreUtility.byteType)
|
||
|
|
{
|
||
|
|
obj = datas[offset];
|
||
|
|
}
|
||
|
|
else if (type == TouchSocketCoreUtility.sbyteType)
|
||
|
|
{
|
||
|
|
obj = (sbyte)(TouchSocketBitConverter.Default.ToInt16(datas, offset));
|
||
|
|
}
|
||
|
|
else if (type == TouchSocketCoreUtility.boolType)
|
||
|
|
{
|
||
|
|
obj = (TouchSocketBitConverter.Default.ToBoolean(datas, offset));
|
||
|
|
}
|
||
|
|
else if (type == TouchSocketCoreUtility.shortType)
|
||
|
|
{
|
||
|
|
obj = (TouchSocketBitConverter.Default.ToInt16(datas, offset));
|
||
|
|
}
|
||
|
|
else if (type == TouchSocketCoreUtility.ushortType)
|
||
|
|
{
|
||
|
|
obj = (TouchSocketBitConverter.Default.ToUInt16(datas, offset));
|
||
|
|
}
|
||
|
|
else if (type == TouchSocketCoreUtility.intType)
|
||
|
|
{
|
||
|
|
obj = (TouchSocketBitConverter.Default.ToInt32(datas, offset));
|
||
|
|
}
|
||
|
|
else if (type == TouchSocketCoreUtility.uintType)
|
||
|
|
{
|
||
|
|
obj = (TouchSocketBitConverter.Default.ToUInt32(datas, offset));
|
||
|
|
}
|
||
|
|
else if (type == TouchSocketCoreUtility.longType)
|
||
|
|
{
|
||
|
|
obj = (TouchSocketBitConverter.Default.ToInt64(datas, offset));
|
||
|
|
}
|
||
|
|
else if (type == TouchSocketCoreUtility.ulongType)
|
||
|
|
{
|
||
|
|
obj = (TouchSocketBitConverter.Default.ToUInt64(datas, offset));
|
||
|
|
}
|
||
|
|
else if (type == TouchSocketCoreUtility.floatType)
|
||
|
|
{
|
||
|
|
obj = (TouchSocketBitConverter.Default.ToSingle(datas, offset));
|
||
|
|
}
|
||
|
|
else if (type == TouchSocketCoreUtility.doubleType)
|
||
|
|
{
|
||
|
|
obj = (TouchSocketBitConverter.Default.ToDouble(datas, offset));
|
||
|
|
}
|
||
|
|
else if (type == TouchSocketCoreUtility.decimalType)
|
||
|
|
{
|
||
|
|
obj = (TouchSocketBitConverter.Default.ToDouble(datas, offset));
|
||
|
|
}
|
||
|
|
else if (type == TouchSocketCoreUtility.charType)
|
||
|
|
{
|
||
|
|
obj = (TouchSocketBitConverter.Default.ToChar(datas, offset));
|
||
|
|
}
|
||
|
|
else if (type == TouchSocketCoreUtility.dateTimeType)
|
||
|
|
{
|
||
|
|
obj = (new DateTime(TouchSocketBitConverter.Default.ToInt64(datas, offset)));
|
||
|
|
}
|
||
|
|
else if (type.BaseType == typeof(Enum))
|
||
|
|
{
|
||
|
|
Type enumType = Enum.GetUnderlyingType(type);
|
||
|
|
|
||
|
|
if (enumType == typeof(byte))
|
||
|
|
{
|
||
|
|
obj = Enum.ToObject(type, datas[offset]);
|
||
|
|
}
|
||
|
|
else if (enumType == typeof(short))
|
||
|
|
{
|
||
|
|
obj = Enum.ToObject(type, TouchSocketBitConverter.Default.ToInt16(datas, offset));
|
||
|
|
}
|
||
|
|
else if (enumType == typeof(int))
|
||
|
|
{
|
||
|
|
obj = Enum.ToObject(type, TouchSocketBitConverter.Default.ToInt32(datas, offset));
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
obj = Enum.ToObject(type, TouchSocketBitConverter.Default.ToInt64(datas, offset));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (type == TouchSocketCoreUtility.bytesType)
|
||
|
|
{
|
||
|
|
byte[] data = new byte[len];
|
||
|
|
Buffer.BlockCopy(datas, offset, data, 0, len);
|
||
|
|
obj = data;
|
||
|
|
}
|
||
|
|
else if (type.IsClass || type.IsStruct())
|
||
|
|
{
|
||
|
|
var serializeObj = GetOrAddInstance(type);
|
||
|
|
if (serializeObj.Converter != null)
|
||
|
|
{
|
||
|
|
obj = serializeObj.Converter.Read(datas, offset, len);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
obj = DeserializeClass(type, datas, offset, len);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
throw new Exception("未定义的类型:" + type.ToString());
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (nullable)
|
||
|
|
{
|
||
|
|
obj = null;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
obj = type.GetDefault();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
offset += len;
|
||
|
|
return obj;
|
||
|
|
}
|
||
|
|
|
||
|
|
private static object DeserializeClass(Type type, byte[] datas, int offset, int length)
|
||
|
|
{
|
||
|
|
SerializObject serializObject = GetOrAddInstance(type);
|
||
|
|
|
||
|
|
object instance;
|
||
|
|
switch (serializObject.InstanceType)
|
||
|
|
{
|
||
|
|
case InstanceType.Class:
|
||
|
|
{
|
||
|
|
instance = serializObject.GetNewInstance();
|
||
|
|
int index = offset;
|
||
|
|
while (offset - index < length && (length >= 4))
|
||
|
|
{
|
||
|
|
int len = datas[offset];
|
||
|
|
string propertyName = Encoding.UTF8.GetString(datas, offset + 1, len);
|
||
|
|
offset += len + 1;
|
||
|
|
if (serializObject.IsStruct)
|
||
|
|
{
|
||
|
|
if (serializObject.PropertiesDic.ContainsKey(propertyName))
|
||
|
|
{
|
||
|
|
PropertyInfo property = serializObject.PropertiesDic[propertyName];
|
||
|
|
object obj = Deserialize(property.PropertyType, datas, ref offset);
|
||
|
|
property.SetValue(instance, obj);
|
||
|
|
}
|
||
|
|
else if (serializObject.FieldInfosDic.ContainsKey(propertyName))
|
||
|
|
{
|
||
|
|
FieldInfo property = serializObject.FieldInfosDic[propertyName];
|
||
|
|
object obj = Deserialize(property.FieldType, datas, ref offset);
|
||
|
|
property.SetValue(instance, obj);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
int pLen = TouchSocketBitConverter.Default.ToInt32(datas, offset);
|
||
|
|
offset += 4;
|
||
|
|
offset += pLen;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (serializObject.PropertiesDic.TryGetValue(propertyName, out PropertyInfo property))
|
||
|
|
{
|
||
|
|
object obj = Deserialize(property.PropertyType, datas, ref offset);
|
||
|
|
serializObject.MemberAccessor.SetValue(instance, property.Name, obj);
|
||
|
|
}
|
||
|
|
else if (serializObject.FieldInfosDic.TryGetValue(propertyName, out FieldInfo fieldInfo))
|
||
|
|
{
|
||
|
|
object obj = Deserialize(fieldInfo.FieldType, datas, ref offset);
|
||
|
|
serializObject.MemberAccessor.SetValue(instance, fieldInfo.Name, obj);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
int pLen = TouchSocketBitConverter.Default.ToInt32(datas, offset);
|
||
|
|
offset += 4;
|
||
|
|
offset += pLen;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case InstanceType.List:
|
||
|
|
{
|
||
|
|
instance = serializObject.GetNewInstance();
|
||
|
|
if (length > 0)
|
||
|
|
{
|
||
|
|
uint paramLen = TouchSocketBitConverter.Default.ToUInt32(datas, offset);
|
||
|
|
offset += 4;
|
||
|
|
for (uint i = 0; i < paramLen; i++)
|
||
|
|
{
|
||
|
|
object obj = Deserialize(serializObject.ArgTypes[0], datas, ref offset);
|
||
|
|
serializObject.AddMethod.Invoke(instance, new object[] { obj });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
instance = null;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case InstanceType.Array:
|
||
|
|
{
|
||
|
|
if (length > 0)
|
||
|
|
{
|
||
|
|
uint paramLen = TouchSocketBitConverter.Default.ToUInt32(datas, offset);
|
||
|
|
Array array = Array.CreateInstance(serializObject.ArrayType, paramLen);
|
||
|
|
|
||
|
|
offset += 4;
|
||
|
|
for (uint i = 0; i < paramLen; i++)
|
||
|
|
{
|
||
|
|
object obj = Deserialize(serializObject.ArrayType, datas, ref offset);
|
||
|
|
array.SetValue(obj, i);
|
||
|
|
}
|
||
|
|
instance = array;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
instance = null;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
case InstanceType.Dictionary:
|
||
|
|
{
|
||
|
|
instance = serializObject.GetNewInstance();
|
||
|
|
if (length > 0)
|
||
|
|
{
|
||
|
|
uint paramLen = TouchSocketBitConverter.Default.ToUInt32(datas, offset);
|
||
|
|
offset += 4;
|
||
|
|
for (uint i = 0; i < paramLen; i++)
|
||
|
|
{
|
||
|
|
object key = Deserialize(serializObject.ArgTypes[0], datas, ref offset);
|
||
|
|
object value = Deserialize(serializObject.ArgTypes[1], datas, ref offset);
|
||
|
|
if (key != null)
|
||
|
|
{
|
||
|
|
serializObject.AddMethod.Invoke(instance, new object[] { key, value });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//uint paramLen = TouchSocketBitConverter.Default.ToUInt32(datas, offset);
|
||
|
|
//offset += 4;
|
||
|
|
//for (uint i = 0; i < paramLen; i++)
|
||
|
|
//{
|
||
|
|
// offset += 4;
|
||
|
|
// offset += datas[offset] + 1;
|
||
|
|
// object key = this.Deserialize(instanceObject.ArgTypes[0], datas, ref offset);
|
||
|
|
|
||
|
|
// offset += datas[offset] + 1;
|
||
|
|
// object value = this.Deserialize(instanceObject.ArgTypes[1], datas, ref offset);
|
||
|
|
// if (key != null)
|
||
|
|
// {
|
||
|
|
// instanceObject.AddMethod.Invoke(instance, new object[] { key, value });
|
||
|
|
// }
|
||
|
|
//}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
instance = null;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
default:
|
||
|
|
instance = null;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
return instance;
|
||
|
|
}
|
||
|
|
|
||
|
|
#endregion Deserialize
|
||
|
|
|
||
|
|
private static SerializObject GetOrAddInstance(Type type)
|
||
|
|
{
|
||
|
|
if (m_instanceCache.TryGetValue(type, out SerializObject instance))
|
||
|
|
{
|
||
|
|
return instance;
|
||
|
|
}
|
||
|
|
if (type.IsArray)//数组
|
||
|
|
{
|
||
|
|
SerializObject instanceObject = new SerializObject(type);
|
||
|
|
m_instanceCache.TryAdd(type, instanceObject);
|
||
|
|
return instanceObject;
|
||
|
|
}
|
||
|
|
else if (type.IsClass || type.IsStruct())
|
||
|
|
{
|
||
|
|
if (type.IsNullableType())
|
||
|
|
{
|
||
|
|
type = type.GetGenericArguments()[0];
|
||
|
|
}
|
||
|
|
|
||
|
|
SerializObject instanceObject = new SerializObject(type);
|
||
|
|
m_instanceCache.TryAdd(type, instanceObject);
|
||
|
|
return instanceObject;
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|