From 03f5809e8aa6110edef33489f2dfc9a46c03a891 Mon Sep 17 00:00:00 2001 From: Loretta Date: Mon, 16 Feb 2026 13:33:15 +0100 Subject: [PATCH] Optimize complex object serialization in source gen Add WriteObjectGenerated to AcBinarySerializer for direct, efficient serialization of complex objects in source-generated code. Update AcBinarySourceGenerator to use this method, including proper handling of nullable properties, to reduce runtime overhead and avoid unnecessary type dispatch. --- .../AcBinarySourceGenerator.cs | 9 +++++++++ .../Binaries/AcBinarySerializer.cs | 20 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/AyCode.Core.Serializers.SourceGenerator/AcBinarySourceGenerator.cs b/AyCode.Core.Serializers.SourceGenerator/AcBinarySourceGenerator.cs index 719df13..38ea653 100644 --- a/AyCode.Core.Serializers.SourceGenerator/AcBinarySourceGenerator.cs +++ b/AyCode.Core.Serializers.SourceGenerator/AcBinarySourceGenerator.cs @@ -158,6 +158,15 @@ public class AcBinarySourceGenerator : IIncrementalGenerator sb.AppendLine($"{i}AcBinarySerializer.WriteStringGenerated({a}, context);"); break; case PropertyTypeKind.Complex: + // Complex object: use WriteObjectGenerated (skips type dispatch in WriteValueNonPrimitive) + if (p.IsNullable) + { + sb.AppendLine($"{i}if ({a} == null) context.WriteByte(BinaryTypeCode.PropertySkip);"); + sb.AppendLine($"{i}else AcBinarySerializer.WriteObjectGenerated({a}, {a}.GetType(), context, depth);"); + } + else + sb.AppendLine($"{i}AcBinarySerializer.WriteObjectGenerated({a}, {a}.GetType(), context, depth);"); + break; case PropertyTypeKind.Collection: if (p.IsNullable) { diff --git a/AyCode.Core/Serializers/Binaries/AcBinarySerializer.cs b/AyCode.Core/Serializers/Binaries/AcBinarySerializer.cs index 807a3e5..7a20084 100644 --- a/AyCode.Core/Serializers/Binaries/AcBinarySerializer.cs +++ b/AyCode.Core/Serializers/Binaries/AcBinarySerializer.cs @@ -499,6 +499,26 @@ public static partial class AcBinarySerializer WriteString(value, context); } + /// + /// Bridge for generated writers: writes a non-null complex OBJECT directly. + /// Skips WriteValueNonPrimitive type dispatch (is byte[]?, is IDictionary?, is IEnumerable?, GetWrapper) + /// because the SrcGen knows at compile-time that the property is a complex object. + /// Uses pre-resolved wrapper type to avoid GetWrapper dictionary lookup. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void WriteObjectGenerated(object value, Type type, BinarySerializationContext context, int depth) + where TOutput : struct, IBinaryOutputBase + { + if (depth > context.MaxDepth) + { + context.WriteByte(BinaryTypeCode.Null); + return; + } + + var wrapper = context.GetWrapper(type); + WriteObject(value, wrapper, context, depth, isNested: depth > 0); + } + #endregion #region Value Writing