Exemple : résolution des problèmes de programmation dynamique
Remarque
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).
Toutes les défaillances de recherche de métadonnées dans les applications développées à l’aide de la chaîne d’outils .NET Native n’entraînent pas d’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 LayoutVM
le type 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 vaut la peine d’identifier et de corriger chaque exception de métadonnées manquante, ou d’économiser du temps et d’ajouter des directives pour une plus grande classe de types. Ici, l’ajout dynamic
de métadonnées App.Core.ViewModels
peut être la meilleure approche si l’augmentation de taille résultante du 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).