public static CodeTypeReference CreateArrayOfCustomTypeReference(string typeName, int arrayRank, Settings settings = null) { if (settings != null) { if (arrayRank > 1) { var type = TypeRefHelper.ArrayAsIEnumerableDerivedToType(typeName, settings.ArrayAs); CodeTypeReference typeReference = new CodeTypeReference(type, new[] { new CodeTypeReference(typeName) }); return(typeReference); } else { var type = TypeRefHelper.ArrayAsIEnumerableDerivedToType(typeName, settings.ArrayAs); CodeTypeReference typeReference = new CodeTypeReference(type); return(typeReference); } } else { CodeTypeReference elementTypeReference = new CodeTypeReference(typeName); CodeTypeReference typeReference = new CodeTypeReference(new CodeTypeReference(), arrayRank) { ArrayElementType = elementTypeReference, }; return(typeReference); } }
/// <summary> /// The Id will be translated to proper C# type name and namespace if the YAML does support namespace in components. /// </summary> /// <param name="item">Reference Id and its schema</param> public override void AddTypeToCodeDom(KeyValuePair <string, OpenApiSchema> item) { string ns = NameFunc.GetNamespaceOfClassName(item.Key); string currentTypeName = NameFunc.RefineTypeName(item.Key, ns); RegisterSchemaRefIdToBeAdded(item.Key); OpenApiSchema schema = item.Value; string type = schema.Type; IList <OpenApiSchema> allOfBaseTypeSchemaList = schema.AllOf; //maybe empty IList <IOpenApiAny> enumTypeList = schema.Enum; //maybe empty bool isForClass = enumTypeList.Count == 0; CodeTypeDeclaration typeDeclaration = null; if (isForClass) { if (schema.Properties.Count > 0 || (schema.Properties.Count == 0 && allOfBaseTypeSchemaList.Count > 1)) { typeDeclaration = AddTypeToClassNamespace(currentTypeName, ns); if (String.IsNullOrEmpty(type) && allOfBaseTypeSchemaList.Count > 0) { OpenApiSchema allOfRef = allOfBaseTypeSchemaList[0]; if (allOfRef.Reference == null) { Trace.TraceWarning($"Not yet support Type {item.Key} having allOf[0] without Reference. Skipped."); RemoveRegisteredSchemaRefId(item.Key); return; } string baseTypeName = NameFunc.RefineTypeName(allOfRef.Reference.Id, ns); //pointing to parent class typeDeclaration.BaseTypes.Add(baseTypeName); if (allOfBaseTypeSchemaList.Count > 1) { OpenApiSchema allOfProperteisSchema = allOfBaseTypeSchemaList[1]; //the 2nd one points to properties of the derived type, while the 1st one points to the base type. AddProperties(typeDeclaration, allOfProperteisSchema, currentTypeName, ns); } } CreateTypeDocComment(item, typeDeclaration); AddProperties(typeDeclaration, schema, currentTypeName, ns); if (settings.DecorateDataModelWithDataContract) { typeDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("System.Runtime.Serialization.DataContract", new CodeAttributeArgument("Namespace", new CodeSnippetExpression($"\"{settings.DataContractNamespace}\"")))); } if (settings.DecorateDataModelWithSerializable) { typeDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("System.SerializableAttribute")); } } else if (type == "array") // wrapper of array. Microsoft OpenApi library could not intepret this as type alias, so I have to register the alias myself. { OpenApiReference itemsRef = schema.Items.Reference; if (itemsRef == null) //Array type with casual schema { if (schema.Items.Properties.Count > 0) //casual member type definition in an array type { string newTypeName = currentTypeName + "Element"; if (FindTypeDeclarationInNamespaces(newTypeName, ns) == null) { AddTypeToCodeDom(new KeyValuePair <string, OpenApiSchema>(newTypeName, schema.Items)); //so add casual type recursively var typeNameX = TypeRefHelper.ArrayAsIEnumerableDerivedToType(newTypeName, settings.ArrayAs); TypeAliasDic.Add(item.Key, typeNameX); Trace.TraceInformation($"TypeAliasDic.Add({item.Key}, {typeNameX}) -- generated: {newTypeName}"); } } else { RemoveRegisteredSchemaRefId(item.Key); Trace.TraceWarning($"Not yet support array type with casual items type without reference and without casual properties: {item.Key}. Skipped."); } return; } string typeNs = NameFunc.GetNamespaceOfClassName(itemsRef.Id); string typeName = NameFunc.RefineTypeName(itemsRef.Id, typeNs); CodeTypeDeclaration existing = FindTypeDeclarationInNamespaces(typeName, typeNs); if (existing == null) //so process itemsRef.Id first before considering type alias { AddTypeToCodeDom(new KeyValuePair <string, OpenApiSchema>(itemsRef.Id, FindSchema(itemsRef.Id))); RemoveRegisteredSchemaRefId(itemsRef.Id); } //Array type with ref to the other type if (TypeAliasDic.TryGet(itemsRef.Id, out string arrayTypeAlias)) { var typeNameX = TypeRefHelper.ArrayAsIEnumerableDerivedToType(arrayTypeAlias, settings.ArrayAs); TypeAliasDic.Add(item.Key, typeNameX); Trace.TraceInformation($"TypeAliasDic.Add({item.Key}, {typeNameX}) with existing ({itemsRef.Id}, {arrayTypeAlias})"); } else { var typeNameX = TypeRefHelper.ArrayAsIEnumerableDerivedToType(itemsRef.Id, settings.ArrayAs); TypeAliasDic.Add(item.Key, typeNameX); Trace.TraceInformation($"TypeAliasDic.Add({item.Key}, {typeNameX})"); } } else if (type != "object" && !String.IsNullOrEmpty(type)) { Type clrType = TypeRefHelper.PrimitiveSwaggerTypeToClrType(type, null); TypeAliasDic.Add(item.Key, clrType.FullName); Trace.TraceInformation($"TypeAliasDic.Add({item.Key}, {clrType.FullName}) -- clrType: {clrType.FullName}"); } else if (type == "object" || String.IsNullOrEmpty(type)) //object alias without properties { typeDeclaration = AddTypeToClassNamespace(currentTypeName, ns); CreateTypeDocComment(item, typeDeclaration); if (settings.DecorateDataModelWithDataContract) { typeDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("System.Runtime.Serialization.DataContract", new CodeAttributeArgument("Namespace", new CodeSnippetExpression($"\"{settings.DataContractNamespace}\"")))); } if (settings.DecorateDataModelWithSerializable) { typeDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("System.SerializableAttribute")); } } else { Trace.TraceInformation($"Type Alias {item.Key} for type {type} is skipped."); RemoveRegisteredSchemaRefId(item.Key); return; } if (typeDeclaration != null) { Trace.TraceInformation($"clientClass {currentTypeName} created for {item.Key}"); } else { Trace.TraceInformation($"Candidate clientClass {currentTypeName} for {item.Key} is skipped"); } } else { typeDeclaration = PodGenHelper.CreatePodClientEnum(ClientNamespace, currentTypeName); CreateTypeDocComment(item, typeDeclaration); AddEnumMembers(typeDeclaration, enumTypeList); if (settings.DecorateDataModelWithDataContract) { typeDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("System.Runtime.Serialization.DataContract", new CodeAttributeArgument("Namespace", new CodeSnippetExpression($"\"{settings.DataContractNamespace}\"")))); //net 5.0 https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-customize-properties#enums-as-strings if (settings.EnumToString) { if (settings.UseSystemTextJson) { //[System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] typeDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("System.Text.Json.Serialization.JsonConverter", new CodeAttributeArgument(new CodeSnippetExpression("typeof(System.Text.Json.Serialization.JsonStringEnumConverter)")))); } else { //[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] typeDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("Newtonsoft.Json.JsonConverter", new CodeAttributeArgument(new CodeSnippetExpression("typeof(Newtonsoft.Json.Converters.StringEnumConverter)")))); } } } if (settings.DecorateDataModelWithSerializable) { typeDeclaration.CustomAttributes.Add(new CodeAttributeDeclaration("System.SerializableAttribute")); } Trace.TraceInformation("client enum: " + currentTypeName); } RemoveRegisteredSchemaRefId(item.Key); }