diff --git a/Svrnty.CQRS.Grpc.Generators/GrpcGenerator.cs b/Svrnty.CQRS.Grpc.Generators/GrpcGenerator.cs index 057e338..62247a5 100644 --- a/Svrnty.CQRS.Grpc.Generators/GrpcGenerator.cs +++ b/Svrnty.CQRS.Grpc.Generators/GrpcGenerator.cs @@ -2009,10 +2009,40 @@ namespace Svrnty.CQRS.Grpc.Generators return $"({prop.Type})(int){accessor}"; } + // Handle nullable numeric types (int?, long?, etc.) + // In protobuf3, numeric fields default to 0 when not set. + // For nullable C# types, we treat 0 as null (unset). + if (prop.IsNullable && IsNullableNumericType(prop.Type)) + { + return $"{accessor} == 0 ? null : {accessor}"; + } + // Default: direct assignment (works for compatible types like int, long, string, bool) return accessor; } + /// + /// Checks if the type is a nullable numeric type (int?, long?, short?, etc.) + /// + private static bool IsNullableNumericType(string typeName) + { + // Check for common nullable numeric types + var nullableNumericTypes = new[] + { + "int?", "System.Int32?", "global::System.Int32?", + "long?", "System.Int64?", "global::System.Int64?", + "short?", "System.Int16?", "global::System.Int16?", + "byte?", "System.Byte?", "global::System.Byte?", + "uint?", "System.UInt32?", "global::System.UInt32?", + "ulong?", "System.UInt64?", "global::System.UInt64?", + "ushort?", "System.UInt16?", "global::System.UInt16?", + "sbyte?", "System.SByte?", "global::System.SByte?", + "float?", "System.Single?", "global::System.Single?", + "double?", "System.Double?", "global::System.Double?", + }; + return nullableNumericTypes.Contains(typeName); + } + /// /// Checks if a type is a collection type and returns the element type if so ///