例:動的プログラミングのトラブルシューティング
注意
このトピックでは、プレリリース ソフトウェアである .NET Native Developer Preview について述べています。 プレビュー版は、Microsoft Connect Web サイトからダウンロードできます (登録が必要です)。
.NET Native ツール チェーンを使用して開発されたアプリでのメタデータ ルックアップの失敗すべてが、例外になるわけではありません。 予測できない方法でアプリに出現するものもあります。 次の例は、null オブジェクトの参照により生じるアクセス違反を示しています。
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]
「Getting Started」(はじめに) の「メタデータの欠落を手動で解決する」セクションで説明されている 3 つの手順からなるアプローチを使用して、この例外をトラブルシューティングしてみましょう。
アプリは何をしていたのか?
最初に注目するのは、スタックの最下位にある async
キーワード メカニズムです。 スタックでは元の呼び出しのコンテキストが失われており、別のスレッドで async
コードを実行しているため、アプリが async
メソッドで実際に何を行っていたかを決定するのは困難です。 ただし、アプリが最初のページをロードしようとしていたことは推測できます。 NavigationArgs.Setup
の実装で、次のコードによってアクセス違反が発生しました。
AppViewModel.Current.LayoutVM.PageMap
この例では、AppViewModel.Current
の LayoutVM
プロパティは 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
のランタイム ディレクティブを追加すると、問題が解決します。 根本原因は、null を返した Type.GetType(String) メソッドへの API 呼び出しで、アプリではクラッシュが発生するまでエラーを出さずにこの問題を無視していました。
動的プログラミングでは、.NET ネイティブの下でリフレクション API を使用する場合、失敗したときに例外をスローする Type.GetType オーバーロードを使用することをお勧めします。
特殊なケースかどうか
App.Core.ViewModels
を使用する際に、その他の問題が発生することもあります。 メタデータの欠落例外すべてを特定して修正する意味があるかどうか、または大きい型のクラスにディレクティブを追加して時間を節約するかを決定する必要があります。 この場合は、出力バイナリのサイズ増大が問題になるのでなければ、App.Core.ViewModels
の dynamic
メタデータを追加するのが最適な方法でしょう。
コードを書き換えることができるか
アプリで typeof(LayoutApplicationVM)
ではなく Type.GetType("LayoutApplicationVM")
を使用している場合、ツール チェーンに browse
メタデータが保存されている可能性があります。 ただし、それでも invoke
メタデータは作成されておらず、そのため型をインスタンス化するときに MissingMetadataException 例外が発生する可能性があります。 この例外を回避するには、名前空間または dynamic
ポリシーを指定する型のランタイム ディレクティブを追加する必要があります。 ランタイム ディレクティブの詳細については、「ランタイム ディレクティブ (rd.xml) 構成ファイル リファレンス」を参照してください。