private (string prepareBlock, string serializeBlock) GetUnionSerializeBlocks(int index, TableMemberModel memberModel) { UnionTypeModel unionModel = (UnionTypeModel)memberModel.ItemTypeModel; string valueVariableName = $"index{index}Value"; string discriminatorOffsetVariableName = $"index{index}DiscriminatorOffset"; string valueOffsetVariableName = $"index{index}ValueOffset"; string discriminatorValueVariableName = $"index{index}Discriminator"; string prepareBlock = $@" var {valueVariableName} = item.{memberModel.PropertyInfo.Name}; int {discriminatorOffsetVariableName} = 0; int {valueOffsetVariableName} = 0; byte {discriminatorValueVariableName} = 0; if ({valueVariableName} != null && {valueVariableName}.Discriminator != 0) {{ {discriminatorValueVariableName} = {valueVariableName}.Discriminator; {discriminatorOffsetVariableName} = currentOffset; vtable.{nameof(VTableBuilder.SetOffset)}({index}, currentOffset - tableStart); currentOffset++; currentOffset += {CSharpHelpers.GetFullMethodName(ReflectedMethods.SerializationHelpers_GetAlignmentErrorMethod)}(currentOffset, sizeof(uint)); {valueOffsetVariableName} = currentOffset; vtable.{nameof(VTableBuilder.SetOffset)}({index + 1}, currentOffset - tableStart); currentOffset += sizeof(uint); }}"; List <string> switchCases = new List <string>(); for (int i = 0; i < unionModel.UnionElementTypeModel.Length; ++i) { var elementModel = unionModel.UnionElementTypeModel[i]; var unionIndex = i + 1; string structAdjustment = string.Empty; if (elementModel.SchemaType == FlatBufferSchemaType.Struct) { // Structs are generally written in-line, with the exception of unions. // So, we need to do the normal allocate space dance here, since we're writing // a pointer to a struct. structAdjustment = $@" var writeOffset = context.{nameof(SerializationContext.AllocateSpace)}({elementModel.InlineSize}, {elementModel.Alignment}); writer.{nameof(SpanWriter.WriteUOffset)}(span, {valueOffsetVariableName}, writeOffset, context); {valueOffsetVariableName} = writeOffset;"; } string @case = $@" case {unionIndex}: {{ {structAdjustment} {this.GetSerializeInvocation(elementModel.ClrType, $"{valueVariableName}.Item{unionIndex}", valueOffsetVariableName)} }} break;"; switchCases.Add(@case); } string serializeBlock = $@" if ({discriminatorOffsetVariableName} != 0) {{ {this.GetSerializeInvocation(typeof(byte), discriminatorValueVariableName, discriminatorOffsetVariableName)} switch ({discriminatorValueVariableName}) {{ {string.Join("\r\n", switchCases)} default: throw new InvalidOperationException(""Unexpected""); }} }}"; return(prepareBlock, serializeBlock); }