Ejemplo: solucionar problemas de programación dinámica
Nota:
En este tema se hace referencia a .NET Native Developer Preview, que es una versión preliminar del software. Puede descargar esta versión preliminar desde el sitio web de Microsoft Connect (es necesario registrarse).
No todos los errores de búsqueda de metadatos en las aplicaciones desarrolladas mediante la cadena de herramientas nativas de .NET producen una excepción. Algunos pueden manifestarse de manera impredecible en una aplicación. En el ejemplo siguiente se muestra una infracción de acceso causada por hacer referencia a un objeto nulo:
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]
Vamos a intentar solucionar esta excepción mediante el enfoque de tres pasos descrito en la sección "Resolver manualmente los metadatos que faltan" de Introducción.
¿Qué estaba haciendo la aplicación?
Lo primero que hay tener en cuenta es la maquinaria de la palabra clave async
en la base de la pila. Determinar lo que la aplicación estaba haciendo realmente en un método async
puede ser problemático, ya que la pila ha perdido el contexto de la llamada original y ha ejecutado el código async
en un subproceso diferente. Sin embargo, podemos deducir que la aplicación estaba intentando cargar su primera página. En la implementación de NavigationArgs.Setup
, el código siguiente produjo la infracción de acceso:
AppViewModel.Current.LayoutVM.PageMap
En esta instancia, la propiedad LayoutVM
en AppViewModel.Current
era NULL. Alguna ausencia de metadatos provocó una diferencia de comportamiento que provocó que una propiedad tuviese un estado no inicializado en vez de establecido, como esperaba la aplicación. Establecer un punto de interrupción en el código donde LayoutVM
debería haberse inicializado podría arrojar luz sobre la situación. Sin embargo, tenga en cuenta que LayoutVM
el tipo es App.Core.ViewModels.Layout.LayoutApplicationVM
. La única directiva de metadatos presente en el archivo rd.xml es:
<Namespace Name="App.ViewModels" Browse="Required Public" Dynamic="Required Public" />
Una causa probable del error es que a App.Core.ViewModels.Layout.LayoutApplicationVM
le falten metadatos porque está en un espacio de nombres diferente.
En este caso, agregar una directiva de tiempo de ejecución para App.Core.ViewModels
ha resuelto el problema. La causa principal ha sido una llamada de la API al método Type.GetType(String) que ha devuelto NULL, y la aplicación ha omitido el problema de forma silenciosa hasta que se ha producido un bloqueo.
En la programación dinámica, se recomienda usar las API de reflexión en .NET Native para usar las Type.GetType sobrecargas que producen una excepción en caso de error.
¿Es un caso aislado?
También pueden surgir otros problemas al utilizar App.Core.ViewModels
. Debe decidir si merece la pena identificar y corregir cada excepción de metadatos que faltan, o bien ahorrar tiempo y agregar directivas para una clase de tipos más grande. Aquí, agregar dynamic
metadatos para App.Core.ViewModels
podría ser el mejor enfoque si el aumento de tamaño resultante del binario de salida no es un problema.
¿Podría modificarse el código?
Si la aplicación hubiera usado typeof(LayoutApplicationVM)
en lugar de Type.GetType("LayoutApplicationVM")
, la cadena de herramientas podría haber conservado los metadatos de browse
. En cambio, aun así no habría creado metadatos de invoke
, que habrían producido una excepción MissingMetadataException al crear una instancia del tipo. Para evitar la excepción, se tendría que agregar una directiva de tiempo de ejecución para el espacio de nombres o el tipo que especifica la directiva dynamic
. Para obtener información sobre las directivas de tiempo de ejecución, vea Referencia del archivo de configuración de directivas en tiempo de ejecución (rd.xml).