Expression Struct(IParser parser, RuntimeSchema schema, bool isBase) { var metadata = schema.HasValue ? Expression.Constant(schema.StructDef.metadata) : noMetadata; var baseSchema = schema.HasBase ? schema.GetBaseSchema() : RuntimeSchema.Empty; return(parser.Apply(new Transform( Begin: () => isBase ? writer.WriteBaseBegin(metadata) : writer.WriteStructBegin(metadata), End: () => isBase ? writer.WriteBaseEnd() : writer.WriteStructEnd(), Fields: schema.HasValue ? from field in schema.StructDef.fields select new Field( Id: field.id, Value: (fieldParser, fieldType) => Expression.Block( writer.WriteFieldBegin(fieldType, field.id, field.metadata), Value(fieldParser, fieldType, schema.GetFieldSchema(field)), writer.WriteFieldEnd()), Omitted: () => writer.WriteFieldOmitted(field.type.id, field.id, field.metadata)) : null, UnknownField: (fieldParser, fieldType, fieldId) => Expression.Block( writer.WriteFieldBegin(fieldType, fieldId, noMetadata), Value(fieldParser, fieldType), writer.WriteFieldEnd()), Base: baseParser => baseSchema.HasValue ? Struct(baseParser, baseSchema, isBase: true) : Expression.Empty(), UnknownEnd: () => writer.WriteBaseEnd()))); }
Expression Struct(IParser parser, Expression var, Type schemaType, bool initialize) { var body = new List <Expression>(); if (initialize) { body.Add(Expression.Assign(var, newObject(var.Type, schemaType))); } ITransform transform; if (parser.HierarchyDepth > schemaType.GetHierarchyDepth()) { // Parser inheritance hierarchy is deeper than the type we are deserializing. // Recurse until hierarchies align. transform = new Transform( Base: baseParser => Struct(baseParser, var, schemaType, initialize: false)); } else { var baseType = schemaType.GetBaseSchemaType(); transform = new Transform( Fields: from field in schemaType.GetSchemaFields() select new Field( Id: field.Id, Value: (fieldParser, fieldType) => FieldValue( fieldParser, DataExpression.PropertyOrField(var, field.Name), fieldType, field.GetSchemaType(), field.GetDefaultValue() == null), Omitted: () => field.GetModifier() == Modifier.Required ? ThrowExpression.RequiredFieldMissingException( field.DeclaringType.Name, Expression.Constant(field.Name)) : Expression.Empty()), Base: baseParser => baseType != null ? Struct(baseParser, Expression.Convert(var, baseType.GetObjectType()), baseType, initialize: false) : Expression.Empty()); } body.Add(parser.Apply(transform)); return(Expression.Block(body)); }