BinarySerializer.Deserialize.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. using System;
  2. using System.Collections;
  3. using System.IO;
  4. using System.Reflection;
  5. using System.Runtime.Serialization;
  6. namespace TBL.CSharp.Serialization.Marshal.Serializer
  7. {
  8. public unsafe partial class BinarySerializer
  9. {
  10. /// <summary>
  11. /// 使用指定上下文反序列化一个可链接符号
  12. /// </summary>
  13. private string DeserializeLinkableSymbol(BinaryReader stream, IMarshalContext context)
  14. {
  15. var typeId = stream.ReadByte();
  16. if (typeId == TBL.CSharp.Serialization.Marshal.Marshal.TypeId.SymbolLink)
  17. {
  18. var symbolId = stream.ReadInt32();
  19. return context.GetLinkableSymbol(symbolId);
  20. }
  21. if (typeId == TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Symbol)
  22. {
  23. string symbol = stream.ReadString();
  24. context.AddLinkableSymbol(symbol);
  25. return symbol;
  26. }
  27. throw new NotSupportedException();
  28. }
  29. /// <summary>
  30. /// 使用指定上下文反序列化一个可链接对象
  31. /// </summary>
  32. private object DeserializeLinkableObject(BinaryReader stream, IMarshalContext context, object target, byte typeId)
  33. {
  34. switch (typeId)
  35. {
  36. // 对象链接
  37. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.ObjectLink:
  38. return context.GetLinkableObject(stream.ReadInt32());
  39. // 字符串
  40. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.String:
  41. string stringValue = stream.ReadString();
  42. return stringValue;
  43. // 其它需要读取类型的对象
  44. default:
  45. var typeName = DeserializeLinkableSymbol(stream, context);
  46. var type = Type.GetType(typeName);
  47. // 未找到符号匹配的类型
  48. if (type == null)
  49. throw new TypeAccessException(typeName);
  50. // 指定了类型不匹配的序列化目标的情况下
  51. if (target != null && target.GetType() != type)
  52. throw new ArgumentException(typeName);
  53. // 如果没有指定序列化目标,则按照类型要求创建对象
  54. if (type.IsArray)
  55. {
  56. // 保持 target
  57. }
  58. else
  59. {
  60. target ??= (TBL.CSharp.Serialization.Marshal.Marshal.TypeId.IsShouldInitialize(typeId)
  61. ? Activator.CreateInstance(type, true)
  62. : FormatterServices.GetUninitializedObject(type));
  63. }
  64. switch (typeId)
  65. {
  66. // 流反序列化
  67. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.SpecialStream:
  68. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.SpecialStreamFull:
  69. ((IStreamSerializable)target)?.Deserialize(stream.BaseStream, _isNeedEndianConversion);
  70. context.AddLinkableObject(target);
  71. return target;
  72. // 代理反序列化
  73. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.SpecialProxied:
  74. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.SpecialProxiedFull:
  75. ((IProxiedSerializable)target)?.ProxiedDeserialize(Deserialize(stream, context, null));
  76. context.AddLinkableObject(target);
  77. return target;
  78. // 不安全反序列化
  79. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.SpecialUnsafe:
  80. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.SpecialUnsafeFull:
  81. {
  82. var size = stream.ReadInt32();
  83. var buffer = stackalloc byte[size];
  84. for (var i = 0; i < size; i++)
  85. buffer[i] = stream.ReadByte();
  86. var realSize = _isNeedEndianConversion ?
  87. ((IUnsafeSerializable)target)?.DeserializeWithEndianConversion(buffer)
  88. : ((IUnsafeSerializable)target)?.Deserialize(buffer);
  89. context.AddLinkableObject(target);
  90. return target;
  91. }
  92. // 一般对象
  93. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Object:
  94. for (;;)
  95. {
  96. switch (stream.ReadByte())
  97. {
  98. // 对象尾部标记,结束处理
  99. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.ObjectEnd:
  100. if (target == null)
  101. {
  102. context.AddLinkableObject(target = FormatterServices.GetUninitializedObject(type));
  103. }
  104. return target;
  105. // 列表标记
  106. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.List:
  107. {
  108. var elementCount = stream.ReadInt32();
  109. if (type.IsArray)
  110. if (target == null)
  111. {
  112. context.AddLinkableObject(target = Activator.CreateInstance(type, elementCount));
  113. }
  114. if (target is not IList list)
  115. throw new NotSupportedException();
  116. if (elementCount != list.Count)
  117. {
  118. if (list.IsFixedSize)
  119. throw new NotSupportedException();
  120. var elementType = type.GenericTypeArguments[0];
  121. var defaultValue = elementType.IsValueType
  122. ? Activator.CreateInstance(elementType)
  123. : null;
  124. var delta = elementCount - list.Count;
  125. if (delta < 0)
  126. {
  127. list.Clear();
  128. }
  129. for (var i = 0; i < delta; i++)
  130. list.Add(defaultValue);
  131. }
  132. for (var i = 0; i < elementCount; i++)
  133. {
  134. list[i] = Deserialize(stream, context, null);
  135. }
  136. break;
  137. }
  138. // 目录标记
  139. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Dictionary:
  140. {
  141. var pairCount = stream.ReadInt32();
  142. if (target == null)
  143. {
  144. context.AddLinkableObject(target = Activator.CreateInstance(type));
  145. }
  146. if (target is not IDictionary dictionary)
  147. throw new NotSupportedException();
  148. for (var i = 0; i < pairCount; i++)
  149. {
  150. var key = Deserialize(stream, context, null);
  151. var element = Deserialize(stream, context, null);
  152. dictionary.Add(key, element);
  153. }
  154. break;
  155. }
  156. // 对象字段标记
  157. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.ObjectFields:
  158. {
  159. var fieldCount = stream.ReadInt32();
  160. if (target == null)
  161. {
  162. context.AddLinkableObject(target = Activator.CreateInstance(type));
  163. }
  164. for (var i = 0; i < fieldCount; i++)
  165. {
  166. var fieldName = DeserializeLinkableSymbol(stream, context);
  167. var fieldInfo = type.GetField(fieldName,
  168. BindingFlags.Instance | BindingFlags.Public |
  169. BindingFlags.NonPublic);
  170. var field = Deserialize(stream, context, null);
  171. fieldInfo?.SetValue(target, field);
  172. }
  173. break;
  174. }
  175. }
  176. }
  177. // 不支持的
  178. default:
  179. throw new NotSupportedException();
  180. }
  181. }
  182. }
  183. /// <summary>
  184. /// 使用指定上下文和指定目标对象进行反序列化
  185. /// <para>如果序列化结果如不匹配,将不会对目标对象进行操作</para>
  186. /// </summary>
  187. private object Deserialize(BinaryReader stream, IMarshalContext context, object target)
  188. {
  189. var typeId = stream.ReadByte();
  190. switch (typeId)
  191. {
  192. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Null: return null;
  193. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.True: return true;
  194. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.False: return false;
  195. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int8: return stream.ReadSByte();
  196. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int8Unsigned: return stream.ReadByte();
  197. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int16: return stream.ReadInt16();
  198. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int16Unsigned: return stream.ReadUInt16();
  199. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int32: return stream.ReadInt32();
  200. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int32Unsigned: return stream.ReadUInt32();
  201. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int64: return stream.ReadInt64();
  202. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int64Unsigned: return stream.ReadUInt64();
  203. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Single:
  204. {
  205. var data = stream.ReadString();
  206. if (data.Equals(nameof(float.NaN)))
  207. return float.NaN;
  208. else if (data.Equals(nameof(float.PositiveInfinity)))
  209. return float.PositiveInfinity;
  210. else if (data.Equals(nameof(float.NegativeInfinity)))
  211. return float.NegativeInfinity;
  212. return Convert.ToSingle(data);
  213. }
  214. case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Double:
  215. {
  216. var data = stream.ReadString();
  217. if (data.Equals(nameof(double.NaN)))
  218. return double.NaN;
  219. else if (data.Equals(nameof(double.PositiveInfinity)))
  220. return double.PositiveInfinity;
  221. else if (data.Equals(nameof(double.NegativeInfinity)))
  222. return double.NegativeInfinity;
  223. return Convert.ToDouble(data);
  224. }
  225. default:
  226. {
  227. return DeserializeLinkableObject(stream, context, target, typeId);
  228. }
  229. }
  230. }
  231. /// <summary>
  232. /// 使用指定上下文和指定目标对象进行反序列化
  233. /// <para>如果序列化结果如不匹配,将不会对目标对象进行操作</para>
  234. /// </summary>
  235. public object Deserialize(Stream stream, IMarshalContext context, object target)
  236. {
  237. using var reader = CreateBinaryReader(stream);
  238. return Deserialize(reader, context, target);
  239. }
  240. }
  241. }