.NET Native环境下GetFields返回空值的解决办法
.NET Native/AOT编译下反射GetFields无返回的解决方法
1. 用特性标记需保留的元数据
在需要反射的目标类型上添加[DynamicDependency]特性,明确告知编译器保留字段的元数据:
using System.Diagnostics.CodeAnalysis; // 保留MyClass的所有字段元数据 [DynamicDependency(DynamicallyAccessedMemberTypes.AllFields, typeof(MyClass))] public class MyClass { public string PublicField; private int PrivateField; }
如果要批量处理多个类型,可在程序入口类上添加多个特性:
[DynamicDependency(DynamicallyAccessedMemberTypes.AllFields, typeof(ClassA))] [DynamicDependency(DynamicallyAccessedMemberTypes.AllFields, typeof(ClassB))] class Program { static void Main(string[] args) { // 业务逻辑 } }
2. 修改项目配置文件保留元数据
若不想逐个添加特性,可通过.csproj文件或裁剪配置文件批量设置:
方式一:直接保留整个程序集
在.csproj中添加以下配置:
<PropertyGroup> <PublishTrimmed>true</PublishTrimmed> </PropertyGroup> <ItemGroup> <!-- 替换为你的程序集名称 --> <TrimmerRootAssembly Include="YourAssemblyName" /> </ItemGroup>
方式二:精细配置保留规则
创建TrimmerConfig.xml文件,内容如下:
<linker> <assembly fullname="YourAssemblyName"> <!-- 保留指定类型的所有元数据 --> <type fullname="YourNamespace.MyClass" preserve="all" /> </assembly> </linker>
然后在.csproj中引用该文件:
<ItemGroup> <TrimmerRootDescriptor Include="TrimmerConfig.xml" /> </ItemGroup>
3. 用UnsafeAccessor替代反射(推荐)
如果是访问私有字段的场景,.NET 7+提供的UnsafeAccessor特性无需反射,性能更高且不受AOT裁剪影响:
using System.Runtime.CompilerServices; public class TargetClass { private int _secretValue = 99; } public static class TargetClassAccessors { [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_secretValue")] public static extern ref int GetSecretValue(TargetClass instance); } // 使用示例 var obj = new TargetClass(); ref int valueRef = ref TargetClassAccessors.GetSecretValue(obj); Console.WriteLine(valueRef); // 输出99
特殊场景:UWP项目
如果是UWP应用,可在Default.rd.xml文件中配置:
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata"> <Application> <!-- 保留指定类型的所有动态元数据 --> <Type Name="YourNamespace.MyClass" Dynamic="Required All" /> </Application> </Directives>
内容的提问来源于stack exchange,提问作者Ryan Wisnesky
相关产品推荐
相关产品推荐

