private string GenerateBody(GeneratorExecutionContext context, TypeDeclarationSyntax tds, bool utcDateTime, List <string> externalInheritances, string ns) { var body = new List <string>(); var members = context.ParseMembers(tds, false, externalInheritances, out bool isPositionalRecord); if (!context.CancellationToken.IsCancellationRequested) { var arrayPropertyType = typeof(ArrayPropertyAttribute); foreach (var member in members) { var(symbol, typeSymbol, nullable) = member; // Object field name var fieldName = symbol.Name; // Field type name var typeName = typeSymbol.GetTypeName(nullable, ns); // ArrayProperty attribute data var arrayData = symbol.GetAttributeData(arrayPropertyType.FullName); // Value part string valuePart; if (typeSymbol.IsSimpleType()) { valuePart = $@"(await reader.GetValueAsync<{typeName}>(""{fieldName}"", names))"; if (utcDateTime && typeSymbol.Name == "DateTime") { valuePart = $"LocalizationUtils.SetUtcKind{valuePart}"; } else if (typeSymbol.Name == "String" && !nullable) { valuePart += "!"; } } else if (typeSymbol.TypeKind == TypeKind.Enum) { // Enum item type var enumSymbol = (INamedTypeSymbol)typeSymbol; var enumType = enumSymbol.EnumUnderlyingType?.Name ?? "Byte"; valuePart = $@"({typeName})(await reader.GetValueAsync<{enumType}>(""{fieldName}"", names))"; } else if (typeSymbol.TypeKind == TypeKind.Array) { // Array type var arraySymbol = (IArrayTypeSymbol)typeSymbol; var itemTypeSymbol = arraySymbol.ElementType; if (!itemTypeSymbol.IsSimpleType()) { continue; } // Splitter var splitter = Extensions.CharToString(arrayData?.GetValue <char?>("Splitter") ?? ','); var arrayType = itemTypeSymbol.Name; if (arrayType.Equals("String")) { valuePart = $@"StringUtils.AsEnumerable(await reader.GetValueAsync<string>(""{fieldName}"", names), '{splitter}').ToArray()"; } else { valuePart = $@"StringUtils.AsEnumerable<{arrayType}>(await reader.GetValueAsync<string>(""{fieldName}"", names), '{splitter}').ToArray()"; } } else if (typeSymbol.IsList()) { // Item type var listSymbol = (INamedTypeSymbol)typeSymbol; var itemTypeSymbol = listSymbol.TypeArguments[0]; if (!itemTypeSymbol.IsSimpleType()) { continue; } // Splitter var splitter = Extensions.CharToString(arrayData?.GetValue <char?>("Splitter") ?? ','); var listType = itemTypeSymbol.Name; if (listType.Equals("String")) { valuePart = $@"StringUtils.AsEnumerable(await reader.GetValueAsync<string>(""{fieldName}"", names), '{splitter}').ToList()"; } else { valuePart = $@"StringUtils.AsEnumerable<{listType}>(await reader.GetValueAsync<string>(""{fieldName}"", names), '{splitter}').ToList()"; } } else { continue; } if (isPositionalRecord) { body.Add($@"{fieldName}: {valuePart}"); } else { body.Add($@"{fieldName} = {valuePart}"); } } } // Limitation: When inheritanted, please keep the same style // Define constructor for Positional Record if (isPositionalRecord) { return("(" + string.Join(",\n", body) + ")"); } return("{\n" + string.Join(",\n", body) + "\n}"); }
private IEnumerable <string> GenerateBody(GeneratorExecutionContext context, TypeDeclarationSyntax tds, bool ignoreNull, bool snakeCase, List <string> externalInheritances) { var body = new List <string>(); var members = context.ParseMembers(tds, true, externalInheritances, out _); if (!context.CancellationToken.IsCancellationRequested) { var propertyType = typeof(PropertyAttribute); var ignoreName = nameof(PropertyAttribute.Ignore); var isAnsiName = nameof(PropertyAttribute.IsAnsi); var fixedLengthName = nameof(PropertyAttribute.FixedLength); var lengthName = nameof(PropertyAttribute.Length); var nameField = nameof(PropertyAttribute.Name); var typeNameField = nameof(PropertyAttribute.TypeName); foreach (var member in members) { var(symbol, typeSymbol, nullable) = member; // Attribute data var attributeData = symbol.GetAttributeData(propertyType.FullName); // Ignore it? var ignore = attributeData?.GetValue <bool?>(ignoreName) ?? false; if (ignore) { continue; } // Is ansi, not unicode var isAnsi = attributeData?.GetValue <bool?>(isAnsiName); var fixedLength = attributeData?.GetValue <bool?>(fixedLengthName); var length = attributeData?.GetValue <int?>(lengthName); // Object field name var fieldName = symbol.Name; // Parameter name var name = attributeData?.GetValue <string>(nameField); if (string.IsNullOrEmpty(name)) { name = snakeCase ? fieldName.ToSnakeCase() : fieldName; } // Data type name var typeName = attributeData?.GetValue <string>(typeNameField); // Line parts string valuePart; // Is dbstring bool isDbString = false; if (typeSymbol.IsSimpleType()) { // Default type name from member's type if (typeName == null || typeName == string.Empty) { typeName = typeSymbol.Name; } // String case if (typeName.Equals("String")) { isDbString = true; valuePart = $"{fieldName}.ToDbString({isAnsi.ToCode()}, {length.ToIntCode()}, {fixedLength.ToCode()})"; } else { valuePart = fieldName; } } else if (typeSymbol.TypeKind == TypeKind.Enum) { // Enum item type if (typeName == null || typeName == string.Empty) { var enumSymbol = (INamedTypeSymbol)typeSymbol; typeName = enumSymbol.EnumUnderlyingType?.Name; if (typeName == null) { typeName = "Byte"; } } valuePart = $"({typeName}){fieldName}"; } else if (typeSymbol.TypeKind == TypeKind.Array) { // Array type var arraySymbol = (IArrayTypeSymbol)typeSymbol; var itemTypeSymbol = arraySymbol.ElementType; if (!itemTypeSymbol.IsSimpleType()) { continue; } var itemDbType = GetDbType(itemTypeSymbol, isAnsi); isDbString = true; if (string.IsNullOrEmpty(typeName)) { // String valuePart = $"app.DB.ListToParameter({fieldName}, {itemDbType}, {length.ToIntCode()}, (type) => SqlServerUtils.GetListCommand(type, app.BuildCommandName))"; } else { // SQL Server TVP valuePart = $"SqlServerUtils.ListToIdRecords({fieldName}, {itemDbType}, {length.ToIntCode()}).AsTableValuedParameter(\"{typeName}\")"; } } else if (typeSymbol.IsList()) { // Item type var listSymbol = (INamedTypeSymbol)typeSymbol; var itemTypeSymbol = listSymbol.TypeArguments[0]; if (!itemTypeSymbol.IsSimpleType()) { continue; } var itemDbType = GetDbType(itemTypeSymbol, isAnsi); isDbString = true; if (string.IsNullOrEmpty(typeName)) { // String valuePart = $"app.DB.ListToParameter({fieldName}, {itemDbType}, {length.ToIntCode()}, (type) => SqlServerUtils.GetListCommand(type, app.BuildCommandName))"; } else { // SQL Server TVP valuePart = $"SqlServerUtils.ListToIdRecords({fieldName}, {itemDbType}, {length.ToIntCode()}).AsTableValuedParameter(\"{typeName}\")"; } } else if (typeSymbol.IsDictionary()) { var dicSymbol = (INamedTypeSymbol)typeSymbol; // Key type var keyType = dicSymbol.TypeArguments[0]; var keyDbType = keyType.Name.ToDbType(); // Item value type var itemType = dicSymbol.TypeArguments[1]; var itemDbType = GetDbType(itemType, isAnsi); isDbString = true; if (string.IsNullOrEmpty(typeName)) { // String valuePart = $"app.DB.DictionaryToTVP({fieldName}, {keyDbType}, {itemDbType}, null, {length.ToIntCode()}, (keyType, valueType) => SqlServerUtils.GetDicCommand(keyType, valueType, app.BuildCommandName))"; } else { // SQL Server TVP valuePart = $"SqlServerUtils.DictionaryToRecords({fieldName}, {keyDbType}, {itemDbType}).AsTableValuedParameter(\"{typeName}\")"; } } else { continue; } // Item var itemCode = new StringBuilder(); if (ignoreNull && (nullable || typeSymbol.IsReferenceType)) { // Ignore null field itemCode.AppendLine($"if({fieldName} != null)"); } if (isDbString) { itemCode.Append($"parameters.Add(\"{name}\", {valuePart})"); } else { itemCode.Append($"parameters.Add(\"{name}\", {valuePart}, {typeName.ToDbType()})"); } body.Add(itemCode.ToString()); } } return(body); }
private string GenerateBody(GeneratorExecutionContext context, TypeDeclarationSyntax tds, List <string> externalInheritances) { var body = new List <string>(); var members = context.ParseMembers(tds, true, externalInheritances, out _); if (!context.CancellationToken.IsCancellationRequested) { foreach (var member in members) { var(symbol, typeSymbol, nullable) = member; // Field name var fieldName = symbol.Name; // Is field or property var isField = (symbol.Kind == SymbolKind.Field).ToCode(); // Is readonly var isReadonly = typeSymbol.IsReadOnly.ToCode(); // Is nullable var isNullable = nullable ? $"{fieldName} == null" : "false"; // Parameter name var pName = "name" + fieldName; // Item var item = new StringBuilder(); if (nullable) { item.AppendLine($@"if({fieldName} == null) w.WriteNull({pName}); else {{ "); } if (typeSymbol.IsSimpleType()) { // Value field var valueField = nullable && typeSymbol.IsValueType ? $"{fieldName}.Value" : fieldName; // typeSymbol.ToString() = "int", typeSymbol.Name = "Int32" var method = GetMethod(typeSymbol.ToString()); item.AppendLine($@"w.{method}({pName}, {valueField});"); } else if (typeSymbol.TypeKind == TypeKind.Enum) { // Enum item type var enumSymbol = (INamedTypeSymbol)typeSymbol; var enumType = enumSymbol.EnumUnderlyingType?.Name ?? "Byte"; item.AppendLine($@"w.WriteNumber({pName}, ({enumType}){fieldName});"); } else if (typeSymbol.TypeKind == TypeKind.Array || typeSymbol.IsList()) { // Type var itemTypeSymbol = typeSymbol.TypeKind == TypeKind.Array ? ((IArrayTypeSymbol)typeSymbol).ElementType : ((INamedTypeSymbol)typeSymbol).TypeArguments[0]; if (!itemTypeSymbol.IsSimpleType()) { item.AppendLine($@"w.WritePropertyName({pName});"); item.AppendLine($@"JsonSerializer.Serialize(w, {fieldName}, options);"); } else { var method = GetMethod(itemTypeSymbol.ToString()) + "Value"; var itemName = "item" + fieldName; item.AppendLine($@"w.WritePropertyName({pName}); w.WriteStartArray(); foreach (var {itemName} in {fieldName}) {{ w.{method}({itemName}); }} w.WriteEndArray(); "); } } else { item.AppendLine($@"w.WritePropertyName({pName});"); item.AppendLine($@"JsonSerializer.Serialize(w, {fieldName}, options);"); } if (nullable) { item.AppendLine("}"); } // Is writable body.Add($@" if (options.IsWritable({isNullable}, {isField}, {isReadonly})) {{ var {pName} = options.ConvertName(""{fieldName}""); {item} }} "); } } return(string.Join("\n", body)); }