Exemplo: solucionando problemas de programação dinâmica
Observação
Este tópico refere-se ao Developer Preview do .NET Nativo, que é um software em pré-lançamento. Você pode baixar a versão prévia do site Microsoft Connect (registro obrigatório).
Nem todas as falhas de pesquisa de metadados em aplicativos desenvolvidos usando a cadeia de ferramentas do .NET Native resultam em uma exceção. Alguns podem manifestar-se de formas imprevisíveis em um aplicativo. O exemplo a seguir mostra uma violação de acesso causada pela referência a um 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 tentar solucionar essa exceção usando a abordagem de três etapas descrita na seção “Resolver manualmente os metadados ausentes” da Introdução.
O que o aplicativo estava fazendo?
A primeira coisa a observar é o maquinário da palavra-chave do async
na base da pilha. Determinar o que o aplicativo fazia em método async
pode ser problemático, porque a pilha perde o contexto da chamada de origem e executa o código async
em um thread diferente. No entanto, podemos deduzir que o aplicativo está tentando carregar sua primeira página. Na implementação de NavigationArgs.Setup
, o seguinte código causou a violação de acesso:
AppViewModel.Current.LayoutVM.PageMap
Nesta instância, a propriedade LayoutVM
em AppViewModel.Current
era null. A ausência de metadados causou uma diferença de comportamento sutil e resultou em uma propriedade sendo não inicializada em vez do conjunto, como o aplicativo esperava. Definir um ponto de interrupção no código onde LayoutVM
deveria ter sido inicializado poderá esclarecer a situação. No entanto, observe que LayoutVM
o tipo App.Core.ViewModels.Layout.LayoutApplicationVM
de . A única diretiva de metadados presente até agora no arquivo rd.xml é:
<Namespace Name="App.ViewModels" Browse="Required Public" Dynamic="Required Public" />
O motivo mais provável da falha é que metadados estão faltando em App.Core.ViewModels.Layout.LayoutApplicationVM
porque ela está em um namespace diferente.
Nesse caso, adicionar uma diretiva de runtime para App.Core.ViewModels
resolveu o problema. A causa raiz foi uma chamada à API ao método Type.GetType(String) que retornou null e o aplicativo ignorou silenciosamente o problema até que ocorreu uma falha.
Na programação dinâmica, uma boa prática ao usar APIs de reflexão no .NET Native é usar as Type.GetType sobrecargas que geram uma exceção em caso de falha.
Esta é uma ocorrência isolada?
Outros problemas também podem surgir ao usar App.Core.ViewModels
. Você deve decidir se vale a pena identificar e corrigir cada exceção de metadados ausente ou economizar tempo e adicionar diretivas para uma classe maior de tipos. Aqui, adicionar dynamic
metadados para App.Core.ViewModels
pode ser a melhor abordagem se o aumento de tamanho resultante do binário de saída não for um problema.
O código pode ser reescrito?
Se o aplicativo tivesse usado typeof(LayoutApplicationVM)
em vez de Type.GetType("LayoutApplicationVM")
, a cadeia de ferramentas poderia ter preservado os metadados browse
. No entanto, ele ainda não criaria os metadados de invoke
, o que levaria a uma exceção MissingMetadataException ao instanciar o tipo. Para evitar a exceção, ainda seria necessário adicionar uma diretiva de runtime para o namespace ou o tipo que especifica a política dynamic
. Para obter informações sobre as diretivas de runtime, consulte a Referência do arquivo de configuração das diretivas de runtime (rd.xml).