internal object ReadImpl(ReadArgs args) { // check id first ulong oid = 0; if (args.TypeData.IsReference) { oid = input.ReadVUInt(); if (TryGetObject(oid, out var result)) return result; } // if expected is not final if (args.TypeData.IsReference && !args.TypeData.IsSealed) args = new ReadArgs((TypeData)ReadImpl(AType), args.TypeHint, args.Instance); object ReturnRegister(object value) { if (oid != 0) Register(oid, value); return value; } // only proceed further if type is supported if (!args.TypeData.IsSupported) return ReturnRegister(new ObjectData(args.TypeData)); // dispatch to appropriate read method if (args.TypeData.Surrogate != null) { return ReturnRegister(ReadSurrogate(args)); } else if (args.TypeData.HasConverter && !settings.IgnoreTypeConverter) { return ReturnRegister(ReadConverter(args)); } else if (args.TypeData.IsISerializable && !settings.IgnoreISerializable) { return ReturnRegister(ReadISerializable(args)); } else { switch (args.TypeData.Kind) { default: case PrimitiveType.None: throw new InvalidOperationException("shouldn't be there"); case PrimitiveType.Object: if (args.TypeData.IsArray) { return ReadArray(args, oid); } else if (args.TypeData.IsNullable) { object o = null; var isNotNull = input.ReadBool(); if (isNotNull) o = ReadImpl(new ReadArgs(args.TypeData.GenericParameters[0])); return ReturnRegister(o); } else if (args.TypeData.IsEnum) { var val = ReadImpl(new ReadArgs(args.TypeData.Element)); var eType = args.InstanceType(readRaw); if (eType != null) { val = Enum.ToObject(eType.Type, val); } else { // leave it as is? // or return an ObjectData? } return ReturnRegister(val); } else { return ReturnRegister(ReadObject(args, oid)); } case PrimitiveType.Type: { var result = new TypeData(); ReturnRegister(result); result.Read(this, input); return result; } case PrimitiveType.String: return ReturnRegister(input.ReadString()); case PrimitiveType.Bytes: return ReturnRegister(input.ReadBytes()); case PrimitiveType.Guid: return ReturnRegister(input.ReadGuid()); case PrimitiveType.Bool: return ReturnRegister(input.ReadBool()); case PrimitiveType.Char: return ReturnRegister(input.ReadChar()); case PrimitiveType.Byte: return ReturnRegister(input.ReadByte()); case PrimitiveType.SByte: return ReturnRegister(input.ReadSByte()); case PrimitiveType.Int16: return ReturnRegister(input.ReadInt16()); case PrimitiveType.UInt16: return ReturnRegister(input.ReadUInt16()); case PrimitiveType.Int32: return ReturnRegister(input.ReadInt32()); case PrimitiveType.UInt32: return ReturnRegister(input.ReadUInt32()); case PrimitiveType.Int64: return ReturnRegister(input.ReadInt64()); case PrimitiveType.UInt64: return ReturnRegister(input.ReadUInt64()); case PrimitiveType.Single: return ReturnRegister(input.ReadSingle()); case PrimitiveType.Double: return ReturnRegister(input.ReadDouble()); case PrimitiveType.Decimal: return ReturnRegister(input.ReadDecimal()); } } }
/// <summary> /// Am even faster way to et known value type, using strongly typed accessor on platform supporting it. /// </summary> /// <param name="reader">The source of the value</param> /// <param name="instance">The instance which member would be set</param> /// <returns>Whether the value could be set. If not the <paramref name="reader"/> won't be read.</returns> public bool TryFastReadSet(IPrimitiveReader reader, object instance) { #if __NET__ || __NETCORE__ if (hasFastSetter && instance != null) { switch (Type.Kind) { case PrimitiveType.Guid: setterGuid(instance, reader.ReadGuid()); break; case PrimitiveType.Bool: setterBool(instance, reader.ReadBool()); break; case PrimitiveType.Char: setterChar(instance, reader.ReadChar()); break; case PrimitiveType.Byte: setterByte(instance, reader.ReadByte()); break; case PrimitiveType.SByte: setterSByte(instance, reader.ReadSByte()); break; case PrimitiveType.Int16: setterInt16(instance, reader.ReadInt16()); break; case PrimitiveType.UInt16: setterUInt16(instance, reader.ReadUInt16()); break; case PrimitiveType.Int32: setterInt32(instance, reader.ReadInt32()); break; case PrimitiveType.UInt32: setterUInt32(instance, reader.ReadUInt32()); break; case PrimitiveType.Int64: setterInt64(instance, reader.ReadInt64()); break; case PrimitiveType.UInt64: setterUInt64(instance, reader.ReadUInt64()); break; case PrimitiveType.Single: setterSingle(instance, reader.ReadSingle()); break; case PrimitiveType.Double: setterDouble(instance, reader.ReadDouble()); break; case PrimitiveType.Decimal: setterDecimal(instance, reader.ReadDecimal()); break; } return(true); } #endif return(false); }