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 { /// /// 使用指定上下文反序列化一个可链接符号 /// 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(); } /// /// 使用指定上下文反序列化一个可链接对象 /// 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(); } } } /// /// 使用指定上下文和指定目标对象进行反序列化 /// 如果序列化结果如不匹配,将不会对目标对象进行操作 /// 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); } } } /// /// 使用指定上下文和指定目标对象进行反序列化 /// 如果序列化结果如不匹配,将不会对目标对象进行操作 /// public object Deserialize(Stream stream, IMarshalContext context, object target) { using var reader = CreateBinaryReader(stream); return Deserialize(reader, context, target); } } }