/// <summary>
        /// Lookup the constructor parameter given its name in the reader.
        /// </summary>
        protected virtual bool TryLookupConstructorParameter(
            ref ReadStack state,
            ref BinaryReader reader,
            BinaryMemberInfo mi,
            BinarySerializerOptions options,
            out BinaryParameterInfo binaryParameterInfo)
        {
            Debug.Assert(state.Current.BinaryClassInfo.ClassType == ClassType.Object);

            ReadOnlySpan <byte> unescapedPropertyName = mi.NameAsUtf8Bytes;

            binaryParameterInfo = state.Current.BinaryClassInfo.GetParameter(
                unescapedPropertyName,
                ref state.Current,
                out byte[] utf8PropertyName);

            // Increment ConstructorParameterIndex so GetParameter() checks the next parameter first when called again.
            state.Current.CtorArgumentState !.ParameterIndex++;

            // For case insensitive and missing property support of BinaryPath, remember the value on the temporary stack.
            state.Current.BinaryPropertyName = utf8PropertyName;

            state.Current.CtorArgumentState.BinaryParameterInfo = binaryParameterInfo;

            return(binaryParameterInfo != null);
        }
        private bool ReadCreatorArgumentsWithContinuation(ref ReadStack state,
                                                          ref BinaryReader reader,
                                                          BinarySerializerOptions options)
        {
            // Process all properties.
            while (true)
            {
                // Determine the property.
                if (state.Current.PropertyState == StackFramePropertyState.None)
                {
                    if (!reader.ReadPropertyName())
                    {
                        return(false);
                    }

                    state.Current.PropertyState = StackFramePropertyState.ReadName;
                }

                BinaryPropertyInfo binaryPropertyInfo;

                if (state.Current.PropertyState <= StackFramePropertyState.Name)
                {
                    state.Current.PropertyState = StackFramePropertyState.Name;

                    BinaryTokenType tokenType = reader.TokenType;

                    if (tokenType == BinaryTokenType.EndObject)
                    {
                        return(true);
                    }

                    // Read method would have thrown if otherwise.
                    Debug.Assert(tokenType == BinaryTokenType.PropertyName);
                    ushort           propertySeq = reader.CurrentPropertySeq;
                    BinaryMemberInfo mi          = state.GetMemberInfo(propertySeq);
                    Debug.Assert(mi != null);


                    binaryPropertyInfo = BinarySerializer.LookupProperty(
                        obj: null !,
                        mi.NameAsUtf8Bytes,
                        ref state,
                        out bool useExtensionProperty,
                        createExtensionProperty: false);

                    state.Current.UseExtensionProperty = useExtensionProperty;
                }
                else
                {
                    binaryPropertyInfo = state.Current.BinaryPropertyInfo;
                }


                if (!HandlePropertyWithContinuation(ref state, ref reader, binaryPropertyInfo !))
                {
                    return(false);
                }
            }
        }
Exemple #3
0
        internal override bool OnTryRead(ref BinaryReader reader, Type typeToConvert, BinarySerializerOptions options, ref ReadStack state, [MaybeNullWhen(false)] out T value)
        {
            object obj;

            if (state.UseFastPath)
            {
                // 刚进入对象读取
                if (reader.CurrentTypeInfo == null || reader.CurrentTypeInfo.SerializeType != ClassType.Object)
                {
                    ThrowHelper.ThrowBinaryException_DeserializeUnableToConvertValue(TypeToConvert);
                }

                reader.AheadReadStartToken();

                if (state.Current.BinaryClassInfo.CreateObject == null)
                {
                    ThrowHelper.ThrowNotSupportedException_DeserializeNoConstructor(state.Current.BinaryClassInfo.Type, ref reader, ref state);
                }

                RefState refState = BinarySerializer.ReadReferenceForObject(this, ref state, ref reader, out object refValue);
                if (refState == RefState.None)
                {
                    obj = state.Current.BinaryClassInfo.CreateObject();
                    state.ReferenceResolver.AddReferenceObject(state.Current.RefId, obj);
                }
                else
                {
                    obj = refValue;
                }


                // Process all properties.
                while (true)
                {
                    reader.AheadReadPropertyName();

                    BinaryPropertyInfo binaryPropertyInfo = null;

                    state.Current.PropertyState = StackFramePropertyState.Name;

                    if (reader.TokenType == BinaryTokenType.EndObject)
                    {
                        break;
                    }

                    Debug.Assert(reader.TokenType == BinaryTokenType.PropertyName);
                    ushort           propertySeq = reader.CurrentPropertySeq;
                    BinaryMemberInfo mi          = state.GetMemberInfo(propertySeq);
                    // Debug.Assert(mi != null);


                    binaryPropertyInfo = BinarySerializer.LookupProperty(
                        obj,
                        mi.NameAsUtf8Bytes,
                        ref state,
                        out bool useExtensionProperty);
                    state.Current.UseExtensionProperty = useExtensionProperty;

                    // binaryPropertyInfo = state.LookupProperty(mi.NameAsString);
                    state.Current.BinaryPropertyInfo           = binaryPropertyInfo;
                    state.Current.PropertyPolymorphicConverter = null;



                    if (binaryPropertyInfo == null)
                    {
                        if (!reader.TrySkip(options))
                        {
                            value = default;
                            return(false);
                        }
                        state.Current.EndProperty();
                        continue;
                    }

                    if (!binaryPropertyInfo.ShouldDeserialize)
                    {
                        if (!reader.TrySkip(options))
                        {
                            state.Current.ReturnValue = obj;
                            value = default;
                            return(false);
                        }

                        state.Current.EndProperty();
                        continue;
                    }


                    // Obtain the CLR value from the Binary and set the member.
                    if (!state.Current.UseExtensionProperty)
                    {
                        binaryPropertyInfo.ReadBinaryAndSetMember(obj, ref state, ref reader);
                    }
                    else
                    {
                        // TODO 扩展属性
                    }

                    state.Current.EndProperty();
                }
            }
            else
            {
                // Slower path that supports continuation and preserved references.
                if (state.Current.ObjectState == StackFrameObjectState.None)
                {
                    // 刚进入对象读取
                    if (reader.CurrentTypeInfo == null || reader.CurrentTypeInfo.SerializeType != ClassType.Object)
                    {
                        ThrowHelper.ThrowBinaryException_DeserializeUnableToConvertValue(TypeToConvert);
                    }

                    if (!reader.ReadStartToken())
                    {
                        value = default;
                        return(false);
                    }


                    RefState refState = BinarySerializer.ReadReferenceForObject(this, ref state, ref reader, out object refValue);
                    if (refState == RefState.None)
                    {
                        state.Current.ObjectState = StackFrameObjectState.StartToken;
                    }
                    else if (refState == RefState.Created)
                    {
                        state.Current.ObjectState = StackFrameObjectState.CreatedObject;
                        state.Current.ReturnValue = refValue;
                    }
                }


                // 创建对象
                if (state.Current.ObjectState < StackFrameObjectState.CreatedObject)
                {
                    if (state.Current.BinaryClassInfo.CreateObject == null)
                    {
                        ThrowHelper.ThrowNotSupportedException_DeserializeNoConstructor(state.Current.BinaryClassInfo.Type, ref reader, ref state);
                    }
                    obj = state.Current.BinaryClassInfo.CreateObject();
                    state.ReferenceResolver.AddReferenceObject(state.Current.RefId, obj);

                    state.Current.ReturnValue = obj;
                    state.Current.ObjectState = StackFrameObjectState.CreatedObject;
                }
                else
                {
                    obj = state.Current.ReturnValue !;
                    Debug.Assert(obj != null);
                }

                // Process all properties.
                while (true)
                {
                    // Determine the property.

                    // 读取属性索引
                    if (state.Current.PropertyState == StackFramePropertyState.None)
                    {
                        if (!reader.ReadPropertyName())
                        {
                            state.Current.ReturnValue = obj;
                            value = default;
                            return(false);
                        }

                        state.Current.PropertyState = StackFramePropertyState.ReadName;

                        //
                    }



                    BinaryPropertyInfo binaryPropertyInfo;
                    if (state.Current.PropertyState <= StackFramePropertyState.ReadName)
                    {
                        state.Current.PropertyState = StackFramePropertyState.Name;

                        if (reader.TokenType == BinaryTokenType.EndObject)
                        {
                            break;
                        }

                        Debug.Assert(reader.TokenType == BinaryTokenType.PropertyName);
                        ushort           propertySeq = reader.CurrentPropertySeq;
                        BinaryMemberInfo mi          = state.GetMemberInfo(propertySeq);
                        Debug.Assert(mi != null);

                        binaryPropertyInfo = BinarySerializer.LookupProperty(
                            obj,
                            mi.NameAsUtf8Bytes,
                            ref state,
                            out bool useExtensionProperty);

                        state.Current.UseExtensionProperty = useExtensionProperty;

                        // binaryPropertyInfo = state.LookupProperty(mi.NameAsString);
                        state.Current.BinaryPropertyInfo           = binaryPropertyInfo;
                        state.Current.PropertyPolymorphicConverter = null;
                        if (binaryPropertyInfo == null)
                        {
                            state.Current.EndProperty();
                            continue;
                        }
                    }
                    else
                    {
                        Debug.Assert(state.Current.BinaryPropertyInfo != null);
                        binaryPropertyInfo = state.Current.BinaryPropertyInfo !;
                    }

                    if (state.Current.PropertyState < StackFramePropertyState.ReadValue)
                    {
                        if (!binaryPropertyInfo.ShouldDeserialize)
                        {
                            if (!reader.TrySkip(options))
                            {
                                state.Current.ReturnValue = obj;
                                value = default;
                                return(false);
                            }

                            state.Current.EndProperty();
                            continue;
                        }
                    }

                    if (state.Current.PropertyState < StackFramePropertyState.TryRead)
                    {
                        // Obtain the CLR value from the Binary and set the member.
                        if (!state.Current.UseExtensionProperty)
                        {
                            if (!binaryPropertyInfo.ReadBinaryAndSetMember(obj, ref state, ref reader))
                            {
                                state.Current.ReturnValue = obj;
                                value = default;
                                return(false);
                            }
                        }
                        else
                        {
                            // TODO 扩展属性
                        }

                        state.Current.EndProperty();
                    }
                }
            }

            // Check if we are trying to build the sorted cache.
            if (state.Current.PropertyRefCache != null)
            {
                state.Current.BinaryClassInfo.UpdateSortedPropertyCache(ref state.Current);
            }

            value = (T)obj;

            return(true);
        }