protected virtual CodeTypeDeclaration processRecord()

in lang/csharp/src/apache/main/CodeGen/CodeGen.cs [738:899]


        protected virtual CodeTypeDeclaration processRecord(Schema schema)
        {
            RecordSchema recordSchema = schema as RecordSchema;
            if (recordSchema == null)
            {
                throw new CodeGenException("Unable to cast schema into a record");
            }

            bool isError = recordSchema.Tag == Schema.Type.Error;

            // declare the class
            var ctd = new CodeTypeDeclaration(CodeGenUtil.Instance.Mangle(recordSchema.Name));
            var baseTypeReference = new CodeTypeReference(
                isError ? typeof(Specific.SpecificException) : typeof(Specific.ISpecificRecord),
                CodeTypeReferenceOptions.GlobalReference);
            ctd.BaseTypes.Add(baseTypeReference);
            ctd.CustomAttributes.Add(CodeGenUtil.Instance.GeneratedCodeAttribute);

            ctd.Attributes = MemberAttributes.Public;
            ctd.IsClass = true;
            ctd.IsPartial = true;

            if (recordSchema.Documentation != null)
            {
                ctd.Comments.Add(createDocComment(recordSchema.Documentation));
            }

            createSchemaField(schema, ctd, isError);

            // declare Get() to be used by the Writer classes
            var cmmGet = new CodeMemberMethod();
            cmmGet.Name = "Get";
            cmmGet.Attributes = MemberAttributes.Public;
            cmmGet.ReturnType = new CodeTypeReference("System.Object");
            cmmGet.Parameters.Add(new CodeParameterDeclarationExpression(typeof(int), "fieldPos"));
            StringBuilder getFieldStmt = new StringBuilder("switch (fieldPos)")
                .AppendLine().AppendLine("\t\t\t{");

            // declare Put() to be used by the Reader classes
            var cmmPut = new CodeMemberMethod();
            cmmPut.Name = "Put";
            cmmPut.Attributes = MemberAttributes.Public;
            cmmPut.ReturnType = new CodeTypeReference(typeof(void));
            cmmPut.Parameters.Add(new CodeParameterDeclarationExpression(typeof(int), "fieldPos"));
            cmmPut.Parameters.Add(new CodeParameterDeclarationExpression("System.Object", "fieldValue"));
            var putFieldStmt = new StringBuilder("switch (fieldPos)")
                .AppendLine().AppendLine("\t\t\t{");

            if (isError)
            {
                cmmGet.Attributes |= MemberAttributes.Override;
                cmmPut.Attributes |= MemberAttributes.Override;
            }

            foreach (Field field in recordSchema.Fields)
            {
                // Determine type of field
                bool nullibleEnum = false;
                string baseType = getType(field.Schema, false, ref nullibleEnum);
                var ctrfield = new CodeTypeReference(baseType);

                // Create field
                string privFieldName = string.Concat("_", field.Name);
                var codeField = new CodeMemberField(ctrfield, privFieldName);
                codeField.Attributes = MemberAttributes.Private;
                if (field.Schema is EnumSchema es && es.Default != null)
                {
                    codeField.InitExpression = new CodeTypeReferenceExpression($"{es.Namespace}.{es.Name}.{es.Default}");
                }

                // Process field documentation if it exist and add to the field
                CodeCommentStatement propertyComment = null;
                if (!string.IsNullOrEmpty(field.Documentation))
                {
                    propertyComment = createDocComment(field.Documentation);
                    if (propertyComment != null)
                    {
                        codeField.Comments.Add(propertyComment);
                    }
                }

                // Add field to class
                ctd.Members.Add(codeField);

                // Create reference to the field - this.fieldname
                var fieldRef = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), privFieldName);
                var mangledName = CodeGenUtil.Instance.Mangle(field.Name);

                // Create field property with get and set methods
                var property = new CodeMemberProperty();
                property.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                property.Name = mangledName;
                property.Type = ctrfield;
                property.GetStatements.Add(new CodeMethodReturnStatement(fieldRef));
                property.SetStatements.Add(new CodeAssignStatement(fieldRef, new CodePropertySetValueReferenceExpression()));
                if (propertyComment != null)
                {
                    property.Comments.Add(propertyComment);
                }

                // Add field property to class
                ctd.Members.Add(property);

                // add to Get()
                getFieldStmt.Append("\t\t\tcase ");
                getFieldStmt.Append(field.Pos);
                getFieldStmt.Append(": return this.");
                getFieldStmt.Append(mangledName);
                getFieldStmt.AppendLine(";");

                // add to Put()
                putFieldStmt.Append("\t\t\tcase ");
                putFieldStmt.Append(field.Pos);
                putFieldStmt.Append(": this.");
                putFieldStmt.Append(mangledName);

                if (nullibleEnum)
                {
                    putFieldStmt.Append(" = fieldValue == null ? (");
                    putFieldStmt.Append(baseType);
                    putFieldStmt.Append(")null : (");

                    string type = baseType.Remove(0, 16);  // remove System.Nullable<
                    type = type.Remove(type.Length - 1);   // remove >

                    putFieldStmt.Append(type);
                    putFieldStmt.AppendLine(")fieldValue; break;");
                }
                else
                {
                    putFieldStmt.Append(" = (");
                    putFieldStmt.Append(baseType);
                    putFieldStmt.AppendLine(")fieldValue; break;");
                }
            }

            // end switch block for Get()
            getFieldStmt.AppendLine("\t\t\tdefault: throw new global::Avro.AvroRuntimeException(\"Bad index \" + fieldPos + \" in Get()\");")
                .Append("\t\t\t}");
            var cseGet = new CodeSnippetExpression(getFieldStmt.ToString());
            cmmGet.Statements.Add(cseGet);
            ctd.Members.Add(cmmGet);

            // end switch block for Put()
            putFieldStmt.AppendLine("\t\t\tdefault: throw new global::Avro.AvroRuntimeException(\"Bad index \" + fieldPos + \" in Put()\");")
                .Append("\t\t\t}");
            var csePut = new CodeSnippetExpression(putFieldStmt.ToString());
            cmmPut.Statements.Add(csePut);
            ctd.Members.Add(cmmPut);

            string nspace = recordSchema.Namespace;
            if (string.IsNullOrEmpty(nspace))
            {
                throw new CodeGenException("Namespace required for record schema " + recordSchema.Name);
            }

            CodeNamespace codens = AddNamespace(nspace);

            codens.Types.Add(ctd);

            return ctd;
        }