Exemple : Résolution des problèmes de programmation dynamique

Notes

Cette rubrique fait référence à .NET Native Developer Preview, qui correspond à la version préliminaire du logiciel. Vous pouvez télécharger la préversion sur le site web Microsoft Connect (inscription nécessaire).

Les échecs de recherche de métadonnées dans les applications développées à l’aide de la chaîne d’outils .NET Native ne utilisent pas toutes une exception. Certains peuvent se manifester de manière imprévisible dans une application. L'exemple suivant montre une violation d'accès provoquée par le référencement d'un objet 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]

Nous allons essayer de résoudre les problèmes liés à cette exception à l’aide de l’approche en trois étapes décrite dans la section « Résoudre manuellement les métadonnées manquantes » de Prise en main.

Que faisait l’application ?

La première chose à noter est le mécanisme de mot clé async à la base de la pile. Déterminer ce que l'application était effectivement en train de faire dans une méthode async peut être problématique, car la pile a perdu le contexte de l'appel d'origine et a exécuté le code async sur un thread différent. Toutefois, nous pouvons déduire que l'application essaie de charger sa première page. Dans l'implémentation de NavigationArgs.Setup, le code suivant a provoqué la violation d'accès :

AppViewModel.Current.LayoutVM.PageMap

Dans ce cas, la propriété LayoutVM sur AppViewModel.Current avait pour valeur null. Une absence de métadonnées a provoqué une différence de comportement subtile et a abouti à la non-initialisation d'une propriété, alors qu'elle devait être définie du point de vue de l'application. Définir un point d'arrêt dans le code là où LayoutVM aurait dû être initialisée peut nous éclairer sur la situation. Toutefois, notez que LayoutVMle type de est App.Core.ViewModels.Layout.LayoutApplicationVM. La seule directive de métadonnées présente jusqu'à présent dans le fichier rd.xml est la suivante :

<Namespace Name="App.ViewModels" Browse="Required Public" Dynamic="Required Public" />

L'échec est peut-être dû à l'absence de métadonnées dans App.Core.ViewModels.Layout.LayoutApplicationVM, car elles se trouvent dans un espace de noms différent.

Dans ce cas, l'ajout d'une directive runtime pour App.Core.ViewModels a résolu le problème. Le problème était dû à un appel d’API en direction de la méthode Type.GetType(String) ayant retourné null, et l’application a ignoré silencieusement le problème jusqu’à ce qu’un incident se produise.

Dans la programmation dynamique, une bonne pratique lors de l’utilisation d’API de réflexion sous .NET Native consiste à utiliser les Type.GetType surcharges qui lèvent une exception en cas d’échec.

S'agit-il d'un cas isolé ?

D'autres problèmes peuvent également survenir pendant l'utilisation d'App.Core.ViewModels. Vous devez décider s’il est utile d’identifier et de corriger chaque exception de métadonnées manquante, ou de gagner du temps et d’ajouter des directives pour une classe de types plus importante. Ici, l’ajout dynamic de métadonnées pour App.Core.ViewModels peut être la meilleure approche si l’augmentation de taille résultante du fichier binaire de sortie n’est pas un problème.

Le code peut-il être réécrit ?

Si l'application a utilisé typeof(LayoutApplicationVM) à la place de Type.GetType("LayoutApplicationVM"), la chaîne d'outils peut avoir conservé des métadonnées browse. Toutefois, elle n’aurait pas créé de métadonnées invoke, ce qui aurait abouti à une exception MissingMetadataException à l’occasion de l’instanciation du type. Pour empêcher cette exception, vous devriez quand même ajouter une directive runtime pour l'espace de noms ou le type qui spécifie la stratégie dynamic. Pour plus d’informations sur les directives runtime, consultez le Guide de référence du fichier de configuration des directives runtime (rd.xml).

Voir aussi