Esempio n. 1
0
        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);
        }