.NET 8 AOT泛型参数无匹配注解引发IL2090错误的解决方法
修复.NET 8 AOT下IL2090反射错误的方案
错误原因
.NET 8 AOT的静态裁剪分析无法确定泛型参数T的哪些成员会被反射访问,因此需要显式告知编译器保留T的公共静态字段,否则这些字段会被AOT裁剪,导致反射调用失败。
方案一:添加动态访问成员注解(推荐)
给泛型参数T添加DynamicallyAccessedMembers注解,指定需要保留的成员类型,让AOT编译器明确要保留T的公共静态字段。
修改后的代码:
using System.Collections.ObjectModel; using System.Diagnostics.CodeAnalysis; using System.Reflection; public static class FieldHelper { public static ReadOnlyCollection<T> GetFields<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicStaticFields)] T>() where T : class { return typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static) .Where(x => x.IsInitOnly && x.FieldType == typeof(T)) .Select(x => (T)x.GetValue(null)) .ToList().AsReadOnly(); } }
注解说明
DynamicallyAccessedMemberTypes.PublicStaticFields:精准匹配你调用GetFields时传入的BindingFlags.Public | BindingFlags.Static筛选条件,告知编译器保留目标类型的公共静态字段。- 使用该注解需要引用
System.Diagnostics.CodeAnalysis命名空间。
方案二:关闭单元测试项目的AOT编译
由于该助手方法仅用于单元测试,而单元测试通常不需要AOT编译,可以修改单元测试项目的.csproj文件,关闭AOT编译开关:
<PropertyGroup> <AotCompile>false</AotCompile> </PropertyGroup>
这样单元测试项目会回到JIT模式,反射代码可正常运行,无需修改任何业务代码。
方案三:使用trim.xml保留成员(灵活性差,不推荐)
若不想修改代码,可在项目根目录创建trim.xml文件,为特定测试类型配置保留规则:
<linker> <assembly fullname="你的程序集名称"> <type fullname="你的命名空间.目标测试类型"> <field name="*" attributes="Public, Static" preserve="all" /> </type> </assembly> </linker>
然后在.csproj中引用该文件:
<ItemGroup> <TrimmerRootDescriptor Include="trim.xml" /> </ItemGroup>
这种方式仅适用于固定的已知类型,因为你的方法是泛型实现,需要为每个测试类型单独配置,灵活性不足。
内容的提问来源于stack exchange,提问作者user246392
相关产品推荐
相关产品推荐

