注释
本主题涉及 .NET Native 开发者预览版,这是预发行的软件。 可以从 Microsoft Connect 网站 下载预览版(需要注册)。
并非所有使用 .NET Native 工具链开发的应用中的元数据查找失败都会导致异常。 某些功能可能会在应用中以不可预知的方式呈现。 以下示例演示由于引用空对象导致的访问权限异常:
Access violation - code c0000005 (first chance)
App!$3_App::Core::Util::NavigationArgs.Setup
App!$3_App::Core::Util::NavigationArgs..ctor
App!$0_App::Gibbon::Util::DesktopNavigationArgs..ctor
App!$0_App::ViewModels::DesktopAppVM.NavigateToPage
App!$3_App::Core::ViewModels::AppViewModel.NavigateToFirstPage
App!$3_App::Core::ViewModels::AppViewModel::<HandleLaunch>d__a.MoveNext
App!$43_System::Runtime::CompilerServices::AsyncMethodBuilderCore.CallMoveNext
App!System::Action.InvokeClosedStaticThunk
App!System::Action.Invoke
App!$43_System::Threading::Tasks::AwaitTaskContinuation.InvokeAction
App!$43_System::Threading::SendOrPostCallback.InvokeOpenStaticThunk
[snip]
让我们尝试使用 入门的“手动解析缺失元数据”部分中概述的三个步骤方法来排查此异常。
应用的作用是什么?
首先需要注意的是堆栈底部的 async
关键字机制。 确定应用在async
方法中真正执行的操作可能是有问题的,因为堆栈丢失了原始调用的上下文,并且已经在不同的线程上运行async
代码。 但是,我们可以推断应用正在尝试加载其第一页。 在实现 NavigationArgs.Setup
中,以下代码导致访问冲突:
AppViewModel.Current.LayoutVM.PageMap
在此实例中,LayoutVM
上的 AppViewModel.Current
属性 null。 某些元数据的缺失导致细微的行为变化,结果是某个属性未被初始化,而未被设置,正如应用程序期望的那样。 在应初始化 LayoutVM
的代码中设置断点可能会帮助我们更好地理解情况。 但是请注意,LayoutVM
的类型是 App.Core.ViewModels.Layout.LayoutApplicationVM
。 rd.xml 文件中目前唯一存在的元数据指令是:
<Namespace Name="App.ViewModels" Browse="Required Public" Dynamic="Required Public" />
发生故障的可能原因是 App.Core.ViewModels.Layout.LayoutApplicationVM
缺少元数据,因为它位于不同的命名空间中。
在这种情况下,添加 App.Core.ViewModels
的运行时指令解决了该问题。 根本原因是对 Type.GetType(String) 返回 null 的方法进行 API 调用,在发生崩溃之前,应用会以无提示方式忽略问题。
在动态编程中,在 .NET Native 下使用反射 API 时,最佳做法是使用在失败时引发异常的 Type.GetType 重载。
这是一个个别案例吗?
使用 App.Core.ViewModels
时也可能出现其他问题。 必须确定它是否值得识别和修复每个缺失的元数据异常,或者节省时间并为更大的类型类添加指令。 在此处,如果输出二进制文件的结果大小增加不是问题,则为 dynamic
添加 App.Core.ViewModels
元数据可能是最佳方法。
是否可以重写代码?
如果该应用使用的是typeof(LayoutApplicationVM)
而非Type.GetType("LayoutApplicationVM")
,那么工具链可以保留browse
的元数据。 但是,它仍然不会创建 invoke
元数据,因此在实例化类型时会导致 MissingMetadataException 异常。 若要防止异常,仍需为命名空间或指定 dynamic
策略的类型添加运行时指令。 有关运行时指令的信息,请参阅 运行时指令(rd.xml)配置文件参考。