private static void HandleStartObject(JsonSerializerOptions options, ref ReadStack state) { if (state.Current.Skip()) { state.Push(); state.Current.Drain = true; return; } if (state.Current.IsDictionary()) { // Fall through and treat as a return value. } else if (state.Current.IsEnumerable() || state.Current.IsPropertyEnumerable() || state.Current.IsPropertyADictionary()) { // An array of objects either on the current property or on a list Type objType = state.Current.GetElementType(); state.Push(); state.Current.JsonClassInfo = options.GetOrAddClass(objType); } else if (state.Current.JsonPropertyInfo != null) { // Nested object Type objType = state.Current.JsonPropertyInfo.RuntimePropertyType; state.Push(); state.Current.JsonClassInfo = options.GetOrAddClass(objType); } JsonClassInfo classInfo = state.Current.JsonClassInfo; state.Current.ReturnValue = classInfo.CreateObject(); }
internal bool TryRead(ref BinaryReader reader, Type typeToConvert, BinarySerializerOptions options, ref ReadStack state, out ReferenceID refId, out T value) { //if (state.Current.BinaryPropertyInfo != null && state.Current.BinaryPropertyInfo.ClassType != ClassType) //{ // // TODO // throw new Exception(); //}else if(state.Current.BinaryPropertyInfo == null && state.Current.BinaryClassInfo!=null && state.Current.BinaryClassInfo.ClassType != ClassType) //{ // throw new Exception(); //} refId = default; if (ClassType == ClassType.Value) { // A value converter should never be within a continuation. //Debug.Assert(!state.IsContinuation); // For perf and converter simplicity, handle null here instead of forwarding to the converter. if (reader.TokenType == BinaryTokenType.Null && !HandleNullOnRead) { if (!CanBeNull) { ThrowHelper.ThrowBinaryException_DeserializeUnableToConvertValue(TypeToConvert); } value = default; return(true); } if (reader.CurrentTypeInfo.Type == TypeEnum.Nullable || // 当Nullable读取需要请求更多数据时,通过此判断进入 //(此时Converter可能已经读取了Nullable的实际类型,reader的当前类型信息已经发生了变化) (state.Current.BinaryClassInfo != null && state.Current.PropertyState > StackFramePropertyState.None && state.Current.BinaryPropertyInfo != null && state.TypeMap.GetTypeInfo(state.Current.BinaryPropertyInfo.TypeSeq).Type == TypeEnum.Nullable)) { state.Push(reader.CurrentTypeInfo); bool isSuccess = OnTryRead(ref reader, typeToConvert, options, ref state, out value); state.Pop(isSuccess); return(isSuccess); } int readCount = GetBytesCount(ref reader, options); // 读取指定数量的字节 if (readCount > 0) { if (!reader.ReadBytes(readCount)) { value = default; return(false); } } else if (readCount == BinarySerializerConstants.BytesCount_Dynamic) { if (!reader.ReadBytes()) { value = default; return(false); } } else if (readCount == BinarySerializerConstants.BytesCount_Auto) { // 自动 bool isContinue = !reader.TryReadValue(out bool isOk); if (!isOk) { ThrowHelper.ThrowBinaryException(); } else if (isContinue) { value = default; return(false); } } // #if !DEBUG // For performance, only perform validation on internal converters on debug builds. if (IsInternalConverter) { value = Read(ref reader, typeToConvert, options); } else // #endif { BinaryTokenType originalPropertyTokenType = reader.TokenType; // int originalPropertyDepth = reader.CurrentDepth; long originalPropertyBytesConsumed = reader.BytesConsumed; value = Read(ref reader, typeToConvert, options); //VerifyRead( // originalPropertyTokenType, // originalPropertyDepth, // originalPropertyBytesConsumed, // isValueConverter: true, // ref reader); } //if (CanBePolymorphic && options.ReferenceHandler != null && value is BinaryElement element) //{ // // Edge case where we want to lookup for a reference when parsing into typeof(object) // // instead of return `value` as a BinaryElement. // Debug.Assert(TypeToConvert == typeof(object)); // if (BinarySerializer.TryGetReferenceFromBinaryElement(ref state, element, out object? referenceValue)) // { // value = (T?)referenceValue; // } //} return(true); } bool success; bool wasContinuation = state.IsContinuation; if (!wasContinuation && reader.TokenType == BinaryTokenType.Null && state.Current.ObjectState < StackFrameObjectState.CreatedObject) { value = default; return(true); } // Remember if we were a continuation here since Push() may affect IsContinuation. // Console.WriteLine(reader.CurrentTypeInfo); // if (!isPolymorphic) // { state.Push(reader.CurrentTypeInfo); // } //if (CanBePolymorphic) //{ // Type type = state.TypeMap.GetType((state.Current.PolymorphicBinaryTypeInfo?? state.Current.BinaryTypeInfo).Seq); // if (type != TypeToConvert) // { // // state.Current // var binaryConverter = state.Current.InitializeReEntry(type, options); // if (binaryConverter != this) // { // // We found a different converter; forward to that. // if (binaryConverter.TryReadAsObject(ref reader, options, ref state, out object tmpValue)) // { // value = (T)tmpValue; // return true; // } // else // { // value = default; // return false; // } // } // } // else // { // } //} // For performance, only perform validation on internal converters on debug builds. if (IsInternalConverter) { if (reader.TokenType == BinaryTokenType.Null && !HandleNullOnRead && !wasContinuation) { if (!CanBeNull) { ThrowHelper.ThrowBinaryException_DeserializeUnableToConvertValue(TypeToConvert); } // For perf and converter simplicity, handle null here instead of forwarding to the converter. value = default; success = true; } else { success = OnTryRead(ref reader, typeToConvert, options, ref state, out value); } } else { if (!wasContinuation) { // For perf and converter simplicity, handle null here instead of forwarding to the converter. if (reader.TokenType == BinaryTokenType.Null && !HandleNullOnRead) { if (!CanBeNull) { ThrowHelper.ThrowBinaryException_DeserializeUnableToConvertValue(TypeToConvert); } value = default; state.Pop(true); return(true); } Debug.Assert(state.Current.OriginalTokenType == BinaryTokenType.None); state.Current.OriginalTokenType = reader.TokenType; Debug.Assert(state.Current.OriginalDepth == 0); // state.Current.OriginalDepth = reader.CurrentDepth; } success = OnTryRead(ref reader, typeToConvert, options, ref state, out value); if (success) { if (state.IsContinuation) { // The resumable converter did not forward to the next converter that previously returned false. ThrowHelper.ThrowBinaryException_SerializationConverterRead(this); } VerifyRead( state.Current.OriginalTokenType, state.Current.OriginalDepth, bytesConsumed: 0, isValueConverter: false, ref reader); // No need to clear state.Current.* since a stack pop will occur. } } if (success && state.Current.RefState == RefState.Start) { refId = (ReferenceID)state.Current.ReturnValue; } // if (!isPolymorphic) // { state.Pop(success); // } return(success); }