如何排查.NET 9 MAUI不应被裁剪的代码?优化运行时诊断
.NET 9 MAUI 裁剪问题排查与调试指南
一、裁剪后应用异常的处理步骤
- 先定位具体错误:裁剪引发的问题大多是
TypeLoadException、MissingMethodException这类反射相关异常,优先捕获并记录报错的类型/方法名 - 回溯编译警告:检查发布过程中输出的IL20xx系列警告,多数运行时问题在编译阶段已有提示,不要忽略这些警告
- 强制保留必要内容:针对报错的类型或成员,通过以下方式确保不被裁剪:
- 使用
[DynamicDependency]特性声明依赖 - 编写rd.xml裁剪配置文件指定保留规则
- 临时将项目的
<TrimMode>设为partial(仅用于排查,不建议正式发布)
- 使用
二、Windows下Visual Studio本地调试裁剪构建
完全可以在本地开发机调试裁剪后的构建,有两种高效方式:
- 通过发布配置调试
- 右键项目 → 「发布」→ 创建本地文件夹类型的发布配置
- 在发布设置中勾选「启用裁剪」,并将「调试信息」设置为「完整」或「仅pdb」
- 发布完成后,直接运行输出目录下的exe,同时在Visual Studio中通过「调试」→「附加到进程」关联该进程进行调试
- 命令行构建调试版裁剪包
打开开发者命令提示符,执行以下命令:
构建完成后,直接启动输出目录中的exe并附加调试即可dotnet publish -f net9.0-windows -c Debug /p:TrimMode=full /p:DebugType=portable
三、Json.Net自定义转换器的裁剪问题解决
针对自定义JsonConverter重写ReadJson时使用Activator.CreateInstance触发IL2091警告的场景:
- 由于重写方法无法添加
[DynamicallyAccessedMembers]特性(会与基类定义冲突),可以采取以下方案:- 临时禁用警告:在项目文件中添加
<NoWarn>$(NoWarn);IL2091</NoWarn>,或在代码中用#pragma warning disable IL2091局部禁用 - 强制保留目标类型:
- 在转换器类上添加
[DynamicDependency]特性声明依赖:[DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(YourTargetType))] public class CustomJsonConverter : JsonConverter { // 你的重写实现 } - 或在rd.xml文件中添加配置:
<Directives> <Type Name="YourTargetType" Dynamic="Required All" /> </Directives>
- 在转换器类上添加
- 临时禁用警告:在项目文件中添加
四、获取运行时诊断信息定位缺失类型
要精准找出被误裁剪的类型,可通过以下手段:
启用裁剪诊断日志
在项目文件中添加配置:<PropertyGroup> <TrimDiagnostics>true</TrimDiagnostics> <TrimOutputPath>$(OutputPath)/trim-logs</TrimOutputPath> </PropertyGroup>发布后,在
trim-logs目录下会生成详细的裁剪记录,搜索报错的类型名称即可查看是否被标记为可裁剪运行时捕获反射失败事件
在应用启动代码中添加以下逻辑,输出反射失败的详细信息:AppDomain.CurrentDomain.TypeResolve += (sender, args) => { Console.WriteLine($"无法解析类型: {args.TypeName}"); return null; }; AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { Console.WriteLine($"无法解析程序集: {args.Name}"); return null; };使用dotnet-dump工具分析崩溃转储
- 应用崩溃时,执行
dotnet-dump collect -p <进程ID>生成转储文件 - 用
dotnet-dump analyze打开转储,通过dumpstack、eeheap -gc等命令定位具体的缺失类型
- 应用崩溃时,执行
内容的提问来源于stack exchange,提问作者DennisWelu
相关产品推荐
相关产品推荐

