private dynamic Read()

in Sources/Runtime/Microsoft.Psi/Serialization/DynamicMessageDeserializer.cs [47:158]


        private dynamic Read(string typeName, BufferReader reader, bool isCollectionElement = false)
        {
            // handle primitive types
            var simpleTypeName = typeName.Split(',')[0]; // without assembly qualification
            switch (simpleTypeName)
            {
                case "System.Boolean":
                    return reader.ReadBool();
                case "System.Byte":
                    return reader.ReadByte();
                case "System.Char":
                    return reader.ReadChar();
                case "System.DateTime":
                    return reader.ReadDateTime();
                case "System.Double":
                    return reader.ReadDouble();
                case "System.Int16":
                    return reader.ReadInt16();
                case "System.Int32":
                    return reader.ReadInt32();
                case "System.Int64":
                    return reader.ReadInt64();
                case "System.SByte":
                    return reader.ReadSByte();
                case "System.Single":
                    return reader.ReadSingle();
                case "System.UInt16":
                    return reader.ReadUInt16();
                case "System.UInt32":
                    return reader.ReadUInt32();
                case "System.UInt64":
                    return reader.ReadUInt64();
            }

            // determine type info and schema
            var isString = simpleTypeName == "System.String";

            if (!isString && !this.schemasByTypeName.ContainsKey(typeName))
            {
                // try custom serializer
                var prefix = typeName.Split('[', ',')[0];
                typeName = $"{prefix}+CustomSerializer{typeName.Substring(prefix.Length)}";
            }

            var schema = isString ? null : this.schemasByTypeName[typeName];
            var isStruct = !isString && (schema.Flags & TypeFlags.IsStruct) != 0;
            var isClass = !isString && (schema.Flags & TypeFlags.IsClass) != 0;
            var isContract = !isString && (schema.Flags & TypeFlags.IsContract) != 0;
            var isCollection = !isString && (schema.Flags & TypeFlags.IsCollection) != 0;

            // reference types and strings (except when members of a collection) have ref-prefix flags
            if (isClass || isCollection || isContract || (isString && !isCollectionElement))
            {
                var prefix = reader.ReadUInt32();
                switch (prefix & SerializationHandler.RefPrefixMask)
                {
                    case SerializationHandler.RefPrefixNull:
                        return null;
                    case SerializationHandler.RefPrefixExisting:
                        // get existing instance from cache
                        return this.instanceCache[(int)(prefix & SerializationHandler.RefPrefixValueMask)];
                    case SerializationHandler.RefPrefixTyped:
                        // update schema to concrete derived type
                        schema = this.schemasById[(int)(prefix & SerializationHandler.RefPrefixValueMask)];
                        break;
                    case SerializationHandler.RefPrefixNew:
                        // fall through to deserialize below
                        break;
                    default:
                        throw new ArgumentException($"Unexpected ref prefix: {prefix}");
                }
            }

            if (isString)
            {
                var str = reader.ReadString();
                this.instanceCache.Add(str);
                return str;
            }

            if (isCollection)
            {
                var len = reader.ReadUInt32();
                var subType = schema.Members[0].Type; // single Elements member describes contained type
                var elements = new dynamic[len];
                this.instanceCache.Add(elements); // add before contents
                for (var i = 0; i < len; i++)
                {
                    elements[i] = this.Read(subType, reader, true);
                }

                return elements;
            }

            var message = new ExpandoObject() as IDictionary<string, dynamic>;
            if (!isStruct)
            {
                this.instanceCache.Add(message); // add before members
            }

            if (schema.Members != null)
            {
                foreach (var mem in schema.Members)
                {
                    var name = mem.Name;
                    var type = mem.Type;
                    message.Add(name, this.Read(type, reader));
                }
            }

            return message;
        }