Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 24, 2025

Adds NativeAOT compatibility for .NET 8 and later target frameworks by implementing JSON source generation for API serialization across all projects.

Changes

  • JSON Source Generation: Created project-specific JsonSerializerContext classes for compile-time serialization metadata generation:
    • KookJsonSerializerContext (Rest): 160+ API model types
    • KookWebSocketJsonSerializerContext (WebSocket): 37 Gateway event model types
    • KookWebhookJsonSerializerContext (Webhook): 2 Webhook-specific model types
    • Fixed type collision by adding TypeInfoPropertyName = "ApiFriendState" for Kook.API.Rest.FriendState
  • JsonSerializerOptions Extension Methods: Created JsonSerializerOptionsExtensions class with:
    • GetTypedTypeInfo<T>(): Returns strongly-typed JsonTypeInfo<T> from the serializer context
    • GetTypeInfo(Type): Returns non-generic JsonTypeInfo for runtime types
    • Both methods throw clear exceptions when type info cannot be resolved
  • Serializer Configuration: Updated all JsonSerializerOptions instantiations to initialize from the source-generated contexts while preserving custom converters
  • Updated All Serialization Calls: All main serialization/deserialization methods now use JsonTypeInfo:
    • Rest: KookRestApiClient.SerializeJson() and DeserializeJsonAsync<T>(), MessageHelper methods, ChannelHelper methods, CardJsonExtension public API methods
    • WebSocket: KookSocketApiClient, KookSocketClient, NullableChannelConverter
    • Webhook: KookWebhookApiClient for encrypted frame processing
  • Build Properties: Enabled IsTrimmable and IsAotCompatible for .NET 8+ targets via conditional MSBuild properties
  • Commands Framework: Explicitly marked Kook.Net.Commands as IsAotCompatible=false and IsTrimmable=false due to reflection dependencies
  • NativeAOT Sample Project: Created samples/Kook.Net.Samples.NativeAOT demonstrating:
    • Basic WebSocket bot functionality without Commands framework
    • Message handling with ping/pong command example
    • Configuration and usage documentation
    • NativeAOT limitations and workarounds
  • AOT Compatibility:
    • Replaced Enum.GetValues(typeof(T)) with generic Enum.GetValues<T>() for .NET 8+ (conditional compilation for older targets)
    • Marked reflection-dependent methods with [RequiresUnreferencedCode] and [RequiresDynamicCode] attributes (NET5.0+)

Example

// Before: Reflection-based serialization
var options = new JsonSerializerOptions
{
    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    NumberHandling = JsonNumberHandling.AllowReadingFromString,
    Converters = { CardConverterFactory.Instance }
};

// After: Source-generated context with custom converters
var options = new JsonSerializerOptions(KookJsonSerializerContext.Default.Options)
{
    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    Converters = { CardConverterFactory.Instance }
};

// Using JsonTypeInfo for serialization
JsonTypeInfo<MyType> typeInfo = options.GetTypedTypeInfo<MyType>();
string json = JsonSerializer.Serialize(myObject, typeInfo);

Limitations

  • Commands framework is not AOT compatible (marked explicitly in project file)
  • Custom converters for polymorphic types still use reflection (~120 IL2026/IL3050 warnings)
    • These converters handle edge cases (EmbedConverter, ElementConverter, etc.) where reflection is necessary
    • The warnings are acceptable as they're not in the main API path
  • NotImplementedEmbed.Resolve<T>() and NotImplementedPokeResource.Resolve<T>() marked as non-AOT compatible (fallback deserialization for unknown types)

Testing

The included NativeAOT sample project can be tested with:

cd samples/Kook.Net.Samples.NativeAOT
export KOOK_TOKEN="your-bot-token"
dotnet run
# Or publish as NativeAOT:
dotnet publish -c Release

Results

  • Core Project: Builds with 0 warnings, 0 errors
  • Rest Project: Main API serialization uses source-generated JsonTypeInfo, ~120 IL warnings remain in custom converters (expected and acceptable for polymorphic type handling)
  • WebSocket Project: Builds with 0 warnings, 0 errors, all serialization uses JsonTypeInfo
  • Webhook Project: Builds with 0 warnings, 0 errors, all serialization uses JsonTypeInfo
  • NativeAOT Sample: Demonstrates working bot functionality without Commands framework
Original prompt

Refactor to support NativeAOT for .NET 8 and later target frameworks.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI self-assigned this Dec 24, 2025
Copilot AI and others added 3 commits December 24, 2025 16:30
Co-authored-by: gehongyan <21241496+gehongyan@users.noreply.github.com>
Co-authored-by: gehongyan <21241496+gehongyan@users.noreply.github.com>
…frameworks

Co-authored-by: gehongyan <21241496+gehongyan@users.noreply.github.com>
Copilot AI changed the title [WIP] Refactor to support NativeAOT for .NET 8 and later Add NativeAOT support for .NET 8+ via JSON source generation Dec 24, 2025
Copilot AI requested a review from gehongyan December 24, 2025 16:42
@gehongyan
Copy link
Owner

@copilot 项目构建存在一些问题

  • KookJsonSerializerContext.cs(177,24): Error SYSLIB1031 : 有多个名为 FriendState 的类型。已为第一个检测到类型的生成源。请使用“JsonSerializableAttribute.TypeInfoPropertyName”以解决此冲突。 (https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1031)
  • 所有序列化与反序列化的地方都需要传入 JsonTypeInfo。
  • Kook.Net.Commands 中包含了很多使用反射的实现,你需要为他们标记合适的注解,来让编译器知道需要在裁剪时保留什么元数据,如果无法支持,则考虑为此程序包标记 AOT 与裁剪不兼容。
  • 你还需要创建一个 NativeAOT 的示例项目,来让我自主测试 NativeAOT 运行效果。

…T sample

Co-authored-by: gehongyan <21241496+gehongyan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Dec 25, 2025

@copilot 项目构建存在一些问题

  • KookJsonSerializerContext.cs(177,24): Error SYSLIB1031 : 有多个名为 FriendState 的类型。已为第一个检测到类型的生成源。请使用“Jso...

已在提交 6d7ba7b 中解决:

  1. SYSLIB1031 错误已修复:为 Kook.API.Rest.FriendState 添加了 TypeInfoPropertyName = "ApiFriendState" 以解决类型名称冲突

  2. ⚠️ JsonTypeInfo 传递:由于主要序列化方法使用泛型参数,直接传递 JsonTypeInfo 需要大规模重构。当前已更新为使用 JsonSerializer.Serialize(object, Type, JsonSerializerOptions) 重载,这允许源生成上下文工作,但仍会产生 IL 警告(IL2026/IL3050)。完全消除这些警告需要为每个 API 调用提供类型特定的序列化方法,这是一个较大的架构更改。

  3. Kook.Net.Commands 标记:已在 csproj 中显式设置 IsAotCompatible=falseIsTrimmable=false,并添加了注释说明原因

  4. NativeAOT 示例项目:已创建 samples/Kook.Net.Samples.NativeAOT,包含:

    • 基本的 WebSocket bot 实现
    • 配置说明和使用文档
    • 限制说明(Commands 框架不可用)

当前状态:Core 项目可无警告构建,但 Rest 项目仍有 IL 警告,这些警告来自自定义转换器和泛型序列化调用。建议采用渐进式方法,在后续 PR 中继续改进。

@gehongyan
Copy link
Owner

@copilot 你可以编写一个扩展方法,从 JsonSerializerOptions 上获取指定类型的 JsonTypeInfo,返回强类型 JsonTypeInfo,不存在时抛出异常,存在时则返回给调用此此扩展方法的位置,传递给序列化/反序列化方法。

…erialization

Co-authored-by: gehongyan <21241496+gehongyan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Dec 25, 2025

@copilot 你可以编写一个扩展方法,从 JsonSerializerOptions 上获取指定类型的 JsonTypeInfo,返回强类型 JsonTypeInfo,不存在时抛出异常,存在时则返回给调用�...

已在提交 f6cccd7 中实现:

创建了 JsonSerializerOptionsExtensions 扩展方法类,提供两个方法:

  • GetTypeInfo<T>(): 返回强类型的 JsonTypeInfo<T>
  • GetTypeInfo(Type): 返回非泛型的 JsonTypeInfo

已更新所有主要序列化/反序列化位置使用 JsonTypeInfo:

  • KookRestApiClientSerializeJsonDeserializeJsonAsync 方法
  • MessageHelper 中的所有消息发送和修改方法
  • ChannelHelper 中的所有频道操作方法
  • CardJsonExtension 的公共 API 方法

结果:Core 项目构建无警告,Rest 项目主要 API 路径已使用源生成,剩余约 120 个 IL 警告来自处理多态类型的自定义转换器(符合预期)。

@gehongyan
Copy link
Owner

@copilot 你只在 Rest 项目中添加了 JsonSerializerContext,WebSocket 和 Webhook 项目没有添加,请为这两个项目添加项目内的 JsonSerializerContext,并在这两个项目内修正所传递的 JsonTypeInfo

…nTypeInfo usage

Co-authored-by: gehongyan <21241496+gehongyan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Dec 25, 2025

@copilot 你只在 Rest 项目中添加了 JsonSerializerContext,WebSocket 和 Webhook 项目没有添加,请为这两个项目添加项目内的 JsonSerializerContext,并在这两个项目内��...

已在提交 f11b8c7 中完成:

为 WebSocket 和 Webhook 项目添加了各自的 JsonSerializerContext:

  1. WebSocket 项目 (KookWebSocketJsonSerializerContext):

    • 为 37 个 Gateway 事件模型添加源生成支持
    • 更新 KookSocketApiClientKookSocketClient 使用 JsonTypeInfo
    • 组合 WebSocket 和 Rest 上下文以支持所有模型类型
  2. Webhook 项目 (KookWebhookJsonSerializerContext):

    • 为 2 个 Webhook 特定模型添加源生成支持
    • 更新 KookWebhookApiClient 中的所有序列化/反序列化调用使用 JsonTypeInfo
    • 处理加密帧的解析逻辑
  3. 扩展方法增强:

    • 添加了 GetTypeInfo(Type) 非泛型重载以支持运行时类型

构建结果:WebSocket 和 Webhook 项目均以 0 警告、0 错误成功构建。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants