123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- using System;
- using System.Collections;
- using System.IO;
- using System.Reflection;
- using System.Runtime.Serialization;
- namespace TBL.CSharp.Serialization.Marshal.Serializer
- {
- public unsafe partial class BinarySerializer
- {
- /// <summary>
- /// 使用指定上下文反序列化一个可链接符号
- /// </summary>
- private string DeserializeLinkableSymbol(BinaryReader stream, IMarshalContext context)
- {
- var typeId = stream.ReadByte();
- if (typeId == TBL.CSharp.Serialization.Marshal.Marshal.TypeId.SymbolLink)
- {
- var symbolId = stream.ReadInt32();
- return context.GetLinkableSymbol(symbolId);
- }
- if (typeId == TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Symbol)
- {
- string symbol = stream.ReadString();
- context.AddLinkableSymbol(symbol);
- return symbol;
- }
- throw new NotSupportedException();
- }
- /// <summary>
- /// 使用指定上下文反序列化一个可链接对象
- /// </summary>
- private object DeserializeLinkableObject(BinaryReader stream, IMarshalContext context, object target, byte typeId)
- {
- switch (typeId)
- {
- // 对象链接
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.ObjectLink:
- return context.GetLinkableObject(stream.ReadInt32());
- // 字符串
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.String:
- string stringValue = stream.ReadString();
- return stringValue;
- // 其它需要读取类型的对象
- default:
- var typeName = DeserializeLinkableSymbol(stream, context);
- var type = Type.GetType(typeName);
-
- // 未找到符号匹配的类型
- if (type == null)
- throw new TypeAccessException(typeName);
- // 指定了类型不匹配的序列化目标的情况下
- if (target != null && target.GetType() != type)
- throw new ArgumentException(typeName);
- // 如果没有指定序列化目标,则按照类型要求创建对象
- if (type.IsArray)
- {
- // 保持 target
- }
- else
- {
- target ??= (TBL.CSharp.Serialization.Marshal.Marshal.TypeId.IsShouldInitialize(typeId)
- ? Activator.CreateInstance(type, true)
- : FormatterServices.GetUninitializedObject(type));
- }
- switch (typeId)
- {
- // 流反序列化
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.SpecialStream:
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.SpecialStreamFull:
- ((IStreamSerializable)target)?.Deserialize(stream.BaseStream, _isNeedEndianConversion);
- context.AddLinkableObject(target);
- return target;
- // 代理反序列化
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.SpecialProxied:
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.SpecialProxiedFull:
- ((IProxiedSerializable)target)?.ProxiedDeserialize(Deserialize(stream, context, null));
- context.AddLinkableObject(target);
- return target;
- // 不安全反序列化
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.SpecialUnsafe:
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.SpecialUnsafeFull:
- {
- var size = stream.ReadInt32();
- var buffer = stackalloc byte[size];
- for (var i = 0; i < size; i++)
- buffer[i] = stream.ReadByte();
- var realSize = _isNeedEndianConversion ?
- ((IUnsafeSerializable)target)?.DeserializeWithEndianConversion(buffer)
- : ((IUnsafeSerializable)target)?.Deserialize(buffer);
- context.AddLinkableObject(target);
- return target;
- }
- // 一般对象
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Object:
- for (;;)
- {
- switch (stream.ReadByte())
- {
- // 对象尾部标记,结束处理
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.ObjectEnd:
- if (target == null)
- {
- context.AddLinkableObject(target = FormatterServices.GetUninitializedObject(type));
- }
- return target;
- // 列表标记
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.List:
- {
- var elementCount = stream.ReadInt32();
- if (type.IsArray)
- if (target == null)
- {
- context.AddLinkableObject(target = Activator.CreateInstance(type, elementCount));
- }
- if (target is not IList list)
- throw new NotSupportedException();
- if (elementCount != list.Count)
- {
- if (list.IsFixedSize)
- throw new NotSupportedException();
- var elementType = type.GenericTypeArguments[0];
- var defaultValue = elementType.IsValueType
- ? Activator.CreateInstance(elementType)
- : null;
- var delta = elementCount - list.Count;
- if (delta < 0)
- {
- list.Clear();
- }
- for (var i = 0; i < delta; i++)
- list.Add(defaultValue);
- }
- for (var i = 0; i < elementCount; i++)
- {
- list[i] = Deserialize(stream, context, null);
- }
- break;
- }
- // 目录标记
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Dictionary:
- {
- var pairCount = stream.ReadInt32();
-
- if (target == null)
- {
- context.AddLinkableObject(target = Activator.CreateInstance(type));
- }
-
- if (target is not IDictionary dictionary)
- throw new NotSupportedException();
-
- for (var i = 0; i < pairCount; i++)
- {
- var key = Deserialize(stream, context, null);
- var element = Deserialize(stream, context, null);
- dictionary.Add(key, element);
- }
-
- break;
- }
- // 对象字段标记
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.ObjectFields:
- {
- var fieldCount = stream.ReadInt32();
-
- if (target == null)
- {
- context.AddLinkableObject(target = Activator.CreateInstance(type));
- }
-
- for (var i = 0; i < fieldCount; i++)
- {
- var fieldName = DeserializeLinkableSymbol(stream, context);
- var fieldInfo = type.GetField(fieldName,
- BindingFlags.Instance | BindingFlags.Public |
- BindingFlags.NonPublic);
- var field = Deserialize(stream, context, null);
- fieldInfo?.SetValue(target, field);
- }
-
- break;
- }
- }
- }
- // 不支持的
- default:
- throw new NotSupportedException();
- }
- }
- }
- /// <summary>
- /// 使用指定上下文和指定目标对象进行反序列化
- /// <para>如果序列化结果如不匹配,将不会对目标对象进行操作</para>
- /// </summary>
- private object Deserialize(BinaryReader stream, IMarshalContext context, object target)
- {
- var typeId = stream.ReadByte();
- switch (typeId)
- {
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Null: return null;
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.True: return true;
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.False: return false;
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int8: return stream.ReadSByte();
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int8Unsigned: return stream.ReadByte();
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int16: return stream.ReadInt16();
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int16Unsigned: return stream.ReadUInt16();
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int32: return stream.ReadInt32();
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int32Unsigned: return stream.ReadUInt32();
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int64: return stream.ReadInt64();
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Int64Unsigned: return stream.ReadUInt64();
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Single:
- {
- var data = stream.ReadString();
- if (data.Equals(nameof(float.NaN)))
- return float.NaN;
- else if (data.Equals(nameof(float.PositiveInfinity)))
- return float.PositiveInfinity;
- else if (data.Equals(nameof(float.NegativeInfinity)))
- return float.NegativeInfinity;
- return Convert.ToSingle(data);
- }
- case TBL.CSharp.Serialization.Marshal.Marshal.TypeId.Double:
- {
- var data = stream.ReadString();
- if (data.Equals(nameof(double.NaN)))
- return double.NaN;
- else if (data.Equals(nameof(double.PositiveInfinity)))
- return double.PositiveInfinity;
- else if (data.Equals(nameof(double.NegativeInfinity)))
- return double.NegativeInfinity;
- return Convert.ToDouble(data);
- }
- default:
- {
- return DeserializeLinkableObject(stream, context, target, typeId);
- }
- }
- }
- /// <summary>
- /// 使用指定上下文和指定目标对象进行反序列化
- /// <para>如果序列化结果如不匹配,将不会对目标对象进行操作</para>
- /// </summary>
- public object Deserialize(Stream stream, IMarshalContext context, object target)
- {
- using var reader = CreateBinaryReader(stream);
- return Deserialize(reader, context, target);
- }
- }
- }
|