123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- using System;
- using System.Collections;
- using System.Globalization;
- using System.IO;
- namespace TBL.CSharp.Serialization.Marshal.Serializer
- {
- public unsafe partial class BinarySerializer : IMarshalSerializer
- {
- /// <summary>
- /// 使用指定上下文序列化一个可链接符号
- /// </summary>
- private void SerializeLinkableSymbol(string symbol, BinaryWriter stream, IMarshalContext context)
- {
- // 在上下文中已链接的符号
- if (context.FindLinkableSymbol(symbol, out var linkedId))
- {
- stream.Write(Marshal.TypeId.SymbolLink);
- stream.Write(linkedId);
- return;
- }
- // 序列化符号
- context.AddLinkableSymbol(symbol);
- stream.Write(Marshal.TypeId.Symbol);
- stream.Write(symbol);
- }
- /// <summary>
- /// 使用指定上下文序列化一个可链接对象
- /// </summary>
- private void SerializeLinkableObject(object self, BinaryWriter stream, IMarshalContext context)
- {
- // 在上下文中已链接的对象
- if (context.FindLinkableObject(self, out var linkedId))
- {
- stream.Write(Marshal.TypeId.ObjectLink);
- stream.Write(linkedId);
- return;
- }
- // 未链接对象的原始处理
- var type = self.GetType();
- context.AddLinkableObject(self);
- switch (self)
- {
- // 字符串对象
- case string stringValue:
- stream.Write(Marshal.TypeId.String);
- stream.Write(stringValue);
- break;
- // 可使用流序列化的对象
- case IStreamSerializable streamSerializable:
- stream.Write(streamSerializable.IsShouldInitializeWhenDeserialize() ? Marshal.TypeId.SpecialStreamFull : Marshal.TypeId.SpecialStream);
- SerializeLinkableSymbol(type.AssemblyQualifiedName, stream, context);
- streamSerializable.Serialize(stream.BaseStream, _isNeedEndianConversion);
- break;
- // 可使用代理序列化的对象
- case IProxiedSerializable proxiedSerializable:
- stream.Write(proxiedSerializable.IsShouldInitializeWhenDeserialize() ? Marshal.TypeId.SpecialProxiedFull : Marshal.TypeId.SpecialProxied);
- SerializeLinkableSymbol(type.AssemblyQualifiedName, stream, context);
- Serialize(proxiedSerializable.ProxiedSerialize(), stream, context);
- break;
- // 可非安全序列化的对象
- case IUnsafeSerializable unsafeSerializable:
- stream.Write(unsafeSerializable.IsShouldInitializeWhenDeserialize() ? Marshal.TypeId.SpecialUnsafeFull : Marshal.TypeId.SpecialUnsafe);
- SerializeLinkableSymbol(type.AssemblyQualifiedName, stream, context);
- var size = unsafeSerializable.CalcSerializationSize();
- var buffer = stackalloc byte[size];
- stream.Write(size);
- var realSize = _isNeedEndianConversion
- ? unsafeSerializable.SerializeWithEndianConversion(buffer)
- : unsafeSerializable.Serialize(buffer);
- for (var i = 0; i < size; i++)
- stream.Write(buffer[i]);
- break;
- // 其它情况
- default:
- // 元组
- if (type.IsSerializableTuple())
- {
- var rt = type.GetGenericArguments();
- stream.Write(Marshal.TypeId.Tuple);
- stream.Write((byte)rt.Length);
- for (int i = 0, len = rt.Length; i < len; i++)
- {
- Serialize(type.GetField($"Item{i}").GetValue(self), stream, context);
- }
- }
- // 一般多字段对象
- else
- {
- stream.Write(Marshal.TypeId.Object);
- SerializeLinkableSymbol(type.AssemblyQualifiedName, stream, context);
- var fieldInfos = Marshal.GetTypeFields(type);
-
- // 序列化列表接口部分
- if (self is IList list)
- {
- stream.Write(Marshal.TypeId.List);
- stream.Write(list.Count);
- foreach (var element in list)
- {
- Serialize(element, stream, context);
- }
- }
-
- // 存储目录部分
- if (self is IDictionary dictionary)
- {
- stream.Write(Marshal.TypeId.Dictionary);
- stream.Write(dictionary.Count);
- foreach (var key in dictionary.Keys)
- {
- Serialize(key, stream, context);
- Serialize(dictionary[key], stream, context);
- }
- }
-
- // 存储字段部分
- if (fieldInfos.Length > 0)
- {
- stream.Write(Marshal.TypeId.ObjectFields);
- stream.Write(fieldInfos.Length);
- foreach (var fieldInfo in fieldInfos)
- {
- SerializeLinkableSymbol(fieldInfo.Name, stream, context);
- Serialize(fieldInfo.GetValue(self), stream, context);
- }
- }
-
- // 对象尾标记
- stream.Write(Marshal.TypeId.ObjectEnd);
- }
- break;
- }
- }
- /// <summary>
- /// 使用指定上下文序列化对象
- /// </summary>
- private void Serialize(object self, BinaryWriter stream, IMarshalContext context)
- {
- switch (self)
- {
- case null:
- stream.Write(Marshal.TypeId.Null);
- break;
- case bool boolValue:
- stream.Write(boolValue ? Marshal.TypeId.True : Marshal.TypeId.False);
- break;
- case sbyte int8Value:
- stream.Write(Marshal.TypeId.Int8);
- stream.Write(int8Value);
- break;
- case byte uint8Value:
- stream.Write(Marshal.TypeId.Int8Unsigned);
- stream.Write(uint8Value);
- break;
- case Int16 int16Value:
- stream.Write(Marshal.TypeId.Int16);
- stream.Write(int16Value);
- break;
- case UInt16 uint16Value:
- stream.Write(Marshal.TypeId.Int16Unsigned);
- stream.Write(uint16Value);
- break;
- case Int32 int32Value:
- stream.Write(Marshal.TypeId.Int32);
- stream.Write(int32Value);
- break;
- case UInt32 uint32Value:
- stream.Write(Marshal.TypeId.Int32Unsigned);
- stream.Write(uint32Value);
- break;
- case Int64 int64Value:
- stream.Write(Marshal.TypeId.Int64);
- stream.Write(int64Value);
- break;
- case UInt64 uint64Value:
- stream.Write(Marshal.TypeId.Int64Unsigned);
- stream.Write(uint64Value);
- break;
- case Single floatValue:
- stream.Write(Marshal.TypeId.Single);
- if (float.IsNaN(floatValue))
- stream.Write(nameof(float.NaN));
- else if (float.IsPositiveInfinity(floatValue))
- stream.Write(nameof(float.PositiveInfinity));
- else if (float.IsNegativeInfinity(floatValue))
- stream.Write(nameof(float.NegativeInfinity));
- else
- stream.Write(Convert.ToString(floatValue, CultureInfo.InvariantCulture));
- break;
- case Double doubleValue:
- stream.Write(Marshal.TypeId.Double);
- if (double.IsNaN(doubleValue))
- stream.Write(nameof(double.NaN));
- else if (double.IsPositiveInfinity(doubleValue))
- stream.Write(nameof(double.PositiveInfinity));
- else if (double.IsNegativeInfinity(doubleValue))
- stream.Write(nameof(double.NegativeInfinity));
- else
- stream.Write(Convert.ToString(doubleValue, CultureInfo.InvariantCulture));
- break;
- default:
- SerializeLinkableObject(self, stream, context);
- break;
- }
- }
- /// <summary>
- /// 使用指定上下文序列化对象
- /// </summary>
- /// <param name="self">要序列化的对象</param>
- /// <param name="stream">序列化目标流</param>
- /// <param name="context">指定的序列化上下文</param>
- public void Serialize(object self, Stream stream, IMarshalContext context)
- {
- using var writer = CreateBinaryWriter(stream);
- Serialize(self, writer, context);
- }
- }
- }
|