dotnetcore / dotnetcore/FreeSql

修复 AOT 编译时产生的 Trimming 警告

Open
#2,007 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C#
Stars
4.4k
Forks
910
PR merge metrics
No merged PRs in 30d

Description

#### Feature 特性

正确标记裁剪不兼容的 API 或为其补充给 ILC 的类型使用信息以消除编译期(发布期)产生的 ILC 警告

#### 简要描述原因

虽然 FreeSql 声明自己支持 AOT,但是在发布期产生的 ILXXXX 警告通常代表 ILC 无法确保给定的 API 在经过裁剪后能够正常运作;所以在源码中对这些依赖动态特性的API进行标注是很重要的,因为这些额外的 Attribute 能够帮助 ILC 决定要保留哪些类型或类型的成员(以使得原本经过裁剪导致错误的API变得可用),以及用户是否使用了根本无法在AOT环境调用的API(以确保AOT发布失败来避免用户获得本就不可用的应用程序)

可以查看 [准备 .NET 库以进行剪裁](https://learn.microsoft.com/zh-cn/dotnet/core/deploying/trimming/prepare-libraries-for-trimming) 文档以获取更多和裁剪 / 正确支持AOT相关的信息

#### 使用场景

对 .Net 应用程序进行 AOT 编译时

#### 亟待解决的 IL 错误汇总

我编写了一个极小的 C# AOT Minimal API 应用程序以检查常见 API 的使用情况,此项目在发布时会产生若干 IL 警告

```csharp
using System.Text.Json.Serialization;
using FreeSql;
using FreeSql.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
using DataType = FreeSql.DataType;

var builder = WebApplication.CreateSlimBuilder(args);

builder.Services.ConfigureHttpJsonOptions(option =>
option.SerializerOptions.TypeInfoResolver = ApplicationJsonContext.Default);
builder.Services.AddSingleton(_ => new FreeSqlBuilder()
// .UseAdoConnectionPool(true)
.UseConnectionString(DataType.Sqlite, "data source=application_data.db")
// .UseMonitorCommand(cmd => Console.WriteLine($"SqlCommand:\n{cmd.CommandText}"))
.UseAutoSyncStructure(true)
.Build()
);

var app = builder.Build();

app.MapGet("/add", async ([FromHeader(Name = nameof(name))] string name, [FromHeader(Name = nameof(score))] int score, IFreeSql sql) =>
{
await sql.InsertOrUpdate().SetSource(new LeaderBoardItem(name, score)).ExecuteAffrowsAsync();
return Results.Ok();
});
app.MapGet("/check", (IFreeSql sql) => sql.Select().ToListAsync());

app.Run();

[JsonSerializable(typeof(List))]
internal partial class ApplicationJsonContext : JsonSerializerContext;

internal record LeaderBoardItem(
[property: Column(IsPrimary = true)] string Name,
int Score
);
```

| 警告类型 | 数量 | 描述 | 示例 | 潜在风险 |
|---------|------|------|------|---------|
| 动态代码生成 (IL3050) | ~50 | 使用需要运行时生成代码的 API | `Expression.Lambda()` | AOT 编译时无法生成代码 |
| 类型反射缺少注释 (IL2070/IL2075) | ~45 | 没有适当 `DynamicallyAccessedMembers` 注解的反射 | `GetType().GetMethods()` | 修剪可能会删除被反射访问的成员 |
| 动态类型创建 (IL3050) | ~35 | 运行时创建泛型类型 | `MakeGenericType()` | AOT 环境无法生成动态类型 |
| 表达式构建 (IL2026) | ~10 | 使用字符串创建属性表达式 | `Expression.Property(expr, "Name")` | 修剪可能移除表达式引用的成员 |
| 单文件部署 (IL3000/IL3002) | 3 | 使用不支持单文件发布的 API | `Assembly.Location` | 在单文件应用中会抛出异常 |

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.