BinarySerializer.Serialize.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. using System;
  2. using System.Collections;
  3. using System.Globalization;
  4. using System.IO;
  5. namespace TBL.CSharp.Serialization.Marshal.Serializer
  6. {
  7. public unsafe partial class BinarySerializer : IMarshalSerializer
  8. {
  9. /// <summary>
  10. /// 使用指定上下文序列化一个可链接符号
  11. /// </summary>
  12. private void SerializeLinkableSymbol(string symbol, BinaryWriter stream, IMarshalContext context)
  13. {
  14. // 在上下文中已链接的符号
  15. if (context.FindLinkableSymbol(symbol, out var linkedId))
  16. {
  17. stream.Write(Marshal.TypeId.SymbolLink);
  18. stream.Write(linkedId);
  19. return;
  20. }
  21. // 序列化符号
  22. context.AddLinkableSymbol(symbol);
  23. stream.Write(Marshal.TypeId.Symbol);
  24. stream.Write(symbol);
  25. }
  26. /// <summary>
  27. /// 使用指定上下文序列化一个可链接对象
  28. /// </summary>
  29. private void SerializeLinkableObject(object self, BinaryWriter stream, IMarshalContext context)
  30. {
  31. // 在上下文中已链接的对象
  32. if (context.FindLinkableObject(self, out var linkedId))
  33. {
  34. stream.Write(Marshal.TypeId.ObjectLink);
  35. stream.Write(linkedId);
  36. return;
  37. }
  38. // 未链接对象的原始处理
  39. var type = self.GetType();
  40. context.AddLinkableObject(self);
  41. switch (self)
  42. {
  43. // 字符串对象
  44. case string stringValue:
  45. stream.Write(Marshal.TypeId.String);
  46. stream.Write(stringValue);
  47. break;
  48. // 可使用流序列化的对象
  49. case IStreamSerializable streamSerializable:
  50. stream.Write(streamSerializable.IsShouldInitializeWhenDeserialize() ? Marshal.TypeId.SpecialStreamFull : Marshal.TypeId.SpecialStream);
  51. SerializeLinkableSymbol(type.AssemblyQualifiedName, stream, context);
  52. streamSerializable.Serialize(stream.BaseStream, _isNeedEndianConversion);
  53. break;
  54. // 可使用代理序列化的对象
  55. case IProxiedSerializable proxiedSerializable:
  56. stream.Write(proxiedSerializable.IsShouldInitializeWhenDeserialize() ? Marshal.TypeId.SpecialProxiedFull : Marshal.TypeId.SpecialProxied);
  57. SerializeLinkableSymbol(type.AssemblyQualifiedName, stream, context);
  58. Serialize(proxiedSerializable.ProxiedSerialize(), stream, context);
  59. break;
  60. // 可非安全序列化的对象
  61. case IUnsafeSerializable unsafeSerializable:
  62. stream.Write(unsafeSerializable.IsShouldInitializeWhenDeserialize() ? Marshal.TypeId.SpecialUnsafeFull : Marshal.TypeId.SpecialUnsafe);
  63. SerializeLinkableSymbol(type.AssemblyQualifiedName, stream, context);
  64. var size = unsafeSerializable.CalcSerializationSize();
  65. var buffer = stackalloc byte[size];
  66. stream.Write(size);
  67. var realSize = _isNeedEndianConversion
  68. ? unsafeSerializable.SerializeWithEndianConversion(buffer)
  69. : unsafeSerializable.Serialize(buffer);
  70. for (var i = 0; i < size; i++)
  71. stream.Write(buffer[i]);
  72. break;
  73. // 其它情况
  74. default:
  75. // 元组
  76. if (type.IsSerializableTuple())
  77. {
  78. var rt = type.GetGenericArguments();
  79. stream.Write(Marshal.TypeId.Tuple);
  80. stream.Write((byte)rt.Length);
  81. for (int i = 0, len = rt.Length; i < len; i++)
  82. {
  83. Serialize(type.GetField($"Item{i}").GetValue(self), stream, context);
  84. }
  85. }
  86. // 一般多字段对象
  87. else
  88. {
  89. stream.Write(Marshal.TypeId.Object);
  90. SerializeLinkableSymbol(type.AssemblyQualifiedName, stream, context);
  91. var fieldInfos = Marshal.GetTypeFields(type);
  92. // 序列化列表接口部分
  93. if (self is IList list)
  94. {
  95. stream.Write(Marshal.TypeId.List);
  96. stream.Write(list.Count);
  97. foreach (var element in list)
  98. {
  99. Serialize(element, stream, context);
  100. }
  101. }
  102. // 存储目录部分
  103. if (self is IDictionary dictionary)
  104. {
  105. stream.Write(Marshal.TypeId.Dictionary);
  106. stream.Write(dictionary.Count);
  107. foreach (var key in dictionary.Keys)
  108. {
  109. Serialize(key, stream, context);
  110. Serialize(dictionary[key], stream, context);
  111. }
  112. }
  113. // 存储字段部分
  114. if (fieldInfos.Length > 0)
  115. {
  116. stream.Write(Marshal.TypeId.ObjectFields);
  117. stream.Write(fieldInfos.Length);
  118. foreach (var fieldInfo in fieldInfos)
  119. {
  120. SerializeLinkableSymbol(fieldInfo.Name, stream, context);
  121. Serialize(fieldInfo.GetValue(self), stream, context);
  122. }
  123. }
  124. // 对象尾标记
  125. stream.Write(Marshal.TypeId.ObjectEnd);
  126. }
  127. break;
  128. }
  129. }
  130. /// <summary>
  131. /// 使用指定上下文序列化对象
  132. /// </summary>
  133. private void Serialize(object self, BinaryWriter stream, IMarshalContext context)
  134. {
  135. switch (self)
  136. {
  137. case null:
  138. stream.Write(Marshal.TypeId.Null);
  139. break;
  140. case bool boolValue:
  141. stream.Write(boolValue ? Marshal.TypeId.True : Marshal.TypeId.False);
  142. break;
  143. case sbyte int8Value:
  144. stream.Write(Marshal.TypeId.Int8);
  145. stream.Write(int8Value);
  146. break;
  147. case byte uint8Value:
  148. stream.Write(Marshal.TypeId.Int8Unsigned);
  149. stream.Write(uint8Value);
  150. break;
  151. case Int16 int16Value:
  152. stream.Write(Marshal.TypeId.Int16);
  153. stream.Write(int16Value);
  154. break;
  155. case UInt16 uint16Value:
  156. stream.Write(Marshal.TypeId.Int16Unsigned);
  157. stream.Write(uint16Value);
  158. break;
  159. case Int32 int32Value:
  160. stream.Write(Marshal.TypeId.Int32);
  161. stream.Write(int32Value);
  162. break;
  163. case UInt32 uint32Value:
  164. stream.Write(Marshal.TypeId.Int32Unsigned);
  165. stream.Write(uint32Value);
  166. break;
  167. case Int64 int64Value:
  168. stream.Write(Marshal.TypeId.Int64);
  169. stream.Write(int64Value);
  170. break;
  171. case UInt64 uint64Value:
  172. stream.Write(Marshal.TypeId.Int64Unsigned);
  173. stream.Write(uint64Value);
  174. break;
  175. case Single floatValue:
  176. stream.Write(Marshal.TypeId.Single);
  177. if (float.IsNaN(floatValue))
  178. stream.Write(nameof(float.NaN));
  179. else if (float.IsPositiveInfinity(floatValue))
  180. stream.Write(nameof(float.PositiveInfinity));
  181. else if (float.IsNegativeInfinity(floatValue))
  182. stream.Write(nameof(float.NegativeInfinity));
  183. else
  184. stream.Write(Convert.ToString(floatValue, CultureInfo.InvariantCulture));
  185. break;
  186. case Double doubleValue:
  187. stream.Write(Marshal.TypeId.Double);
  188. if (double.IsNaN(doubleValue))
  189. stream.Write(nameof(double.NaN));
  190. else if (double.IsPositiveInfinity(doubleValue))
  191. stream.Write(nameof(double.PositiveInfinity));
  192. else if (double.IsNegativeInfinity(doubleValue))
  193. stream.Write(nameof(double.NegativeInfinity));
  194. else
  195. stream.Write(Convert.ToString(doubleValue, CultureInfo.InvariantCulture));
  196. break;
  197. default:
  198. SerializeLinkableObject(self, stream, context);
  199. break;
  200. }
  201. }
  202. /// <summary>
  203. /// 使用指定上下文序列化对象
  204. /// </summary>
  205. /// <param name="self">要序列化的对象</param>
  206. /// <param name="stream">序列化目标流</param>
  207. /// <param name="context">指定的序列化上下文</param>
  208. public void Serialize(object self, Stream stream, IMarshalContext context)
  209. {
  210. using var writer = CreateBinaryWriter(stream);
  211. Serialize(self, writer, context);
  212. }
  213. }
  214. }