/// <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);
        }
        protected override bool ReadAndCacheConstructorArgument(
            ref ReadStack state,
            ref BinaryReader reader,
            BinaryParameterInfo binaryParameterInfo)
        {
            Debug.Assert(state.Current.CtorArgumentState !.Arguments != null);
            var arguments = (Arguments <TArg0, TArg1, TArg2, TArg3>)state.Current.CtorArgumentState.Arguments;

            bool success;

            switch (binaryParameterInfo.Position)
            {
            case 0:
                success = TryRead <TArg0>(ref state, ref reader, binaryParameterInfo, out arguments.Arg0);
                break;

            case 1:
                success = TryRead <TArg1>(ref state, ref reader, binaryParameterInfo, out arguments.Arg1);
                break;

            case 2:
                success = TryRead <TArg2>(ref state, ref reader, binaryParameterInfo, out arguments.Arg2);
                break;

            case 3:
                success = TryRead <TArg3>(ref state, ref reader, binaryParameterInfo, out arguments.Arg3);
                break;

            default:
                Debug.Fail("More than 4 params: we should be in override for LargeObjectWithParameterizedConstructorConverter.");
                throw new InvalidOperationException();
            }

            return(success);
        }
        private bool TryRead <TArg>(
            ref ReadStack state,
            ref BinaryReader reader,
            BinaryParameterInfo binaryParameterInfo,
            out TArg arg)
        {
            Debug.Assert(binaryParameterInfo.ShouldDeserialize);
            Debug.Assert(binaryParameterInfo.Options != null);

            var info = (BinaryParameterInfo <TArg>)binaryParameterInfo;

            var converter = (BinaryConverter <TArg>)binaryParameterInfo.ConverterBase;

            bool success;

            if (state.Current.PropertyState < StackFramePropertyState.TryReadTypeSeq)
            {
                if (!reader.ReadTypeSeq())
                {
                    arg = default;
                    return(false);
                }
                state.Current.PropertyState = StackFramePropertyState.TryReadTypeSeq;
                if (state.Current.PropertyPolymorphicConverter == null && reader.CurrentTypeInfo != null && converter.CanBePolymorphic)
                {
                    var type = state.TypeMap.GetType(reader.CurrentTypeInfo.Seq);
                    if (type != null && type != converter.TypeToConvert && converter.TypeToConvert.IsAssignableFrom(type))
                    {
                        state.Current.PropertyPolymorphicConverter = state.Current.InitializeReEntry(type, state.Options);
                    }
                }
            }

            TArg value = default;

            if (state.Current.PropertyPolymorphicConverter != null)
            {
                success = state.Current.PropertyPolymorphicConverter.TryReadAsObject(ref reader, state.Options, ref state, out object tmpValue);
                if (success)
                {
                    value = (TArg)tmpValue;
                }
            }
            else
            {
                success = converter.TryRead(ref reader, info.RuntimePropertyType, info.Options !, ref state, out _, out value);
            }

            arg = value == null && binaryParameterInfo.IgnoreDefaultValuesOnRead
                ? (TArg)info.DefaultValue ! // Use default value specified on parameter, if any.
                : value !;

            return(success);
        }
Exemple #4
0
 public ParameterRef(ulong key, BinaryParameterInfo info, byte[] nameFromBinary)
 {
     Key            = key;
     Info           = info;
     NameFromBinary = nameFromBinary;
 }
        protected override bool ReadAndCacheConstructorArgument(ref ReadStack state, ref BinaryReader reader, BinaryParameterInfo binaryParameterInfo)
        {
            Debug.Assert(binaryParameterInfo.ShouldDeserialize);
            Debug.Assert(binaryParameterInfo.Options != null);

            var converter = binaryParameterInfo.ConverterBase;

            bool success;


            if (state.Current.PropertyState < StackFramePropertyState.TryReadTypeSeq)
            {
                if (!reader.ReadTypeSeq())
                {
                    return(false);
                }
                state.Current.PropertyState = StackFramePropertyState.TryReadTypeSeq;
                if (state.Current.PropertyPolymorphicConverter == null && reader.CurrentTypeInfo != null && converter.CanBePolymorphic)
                {
                    var type = state.TypeMap.GetType(reader.CurrentTypeInfo.Seq);
                    if (type != null && type != converter.TypeToConvert && converter.TypeToConvert.IsAssignableFrom(type))
                    {
                        state.Current.PropertyPolymorphicConverter = state.Current.InitializeReEntry(type, state.Options);
                    }
                }
            }

            object arg;

            if (state.Current.PropertyPolymorphicConverter != null)
            {
                success = state.Current.PropertyPolymorphicConverter.TryReadAsObject(ref reader, state.Options, ref state, out arg);
            }
            else
            {
                success = converter.TryReadAsObject(ref reader, binaryParameterInfo.Options !, ref state, out arg);
            }

            if (success && !(arg == null && binaryParameterInfo.IgnoreDefaultValuesOnRead))
            {
                ((object[])state.Current.CtorArgumentState !.Arguments)[binaryParameterInfo.Position] = arg !;