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;
}