FreeSql icon indicating copy to clipboard operation
FreeSql copied to clipboard

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

Open Delsin-Yu opened this issue 10 months ago • 0 comments

Feature 特性

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

简要描述原因

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

可以查看 准备 .NET 库以进行剪裁 文档以获取更多和裁剪 / 正确支持AOT相关的信息

使用场景

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

亟待解决的 IL 错误汇总

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

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<IFreeSql>(_ => 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<LeaderBoardItem>().SetSource(new LeaderBoardItem(name, score)).ExecuteAffrowsAsync();
    return Results.Ok();
});
app.MapGet("/check", (IFreeSql sql) => sql.Select<LeaderBoardItem>().ToListAsync());

app.Run();

[JsonSerializable(typeof(List<LeaderBoardItem>))]
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 在单文件应用中会抛出异常

Delsin-Yu avatar Apr 15 '25 13:04 Delsin-Yu