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);
}
}
}