Partilhar via


Estender a Recarga Dinâmica do .NET usando MetadataUpdateHandler (C#, Visual Basic)

Você pode estender programaticamente o suporte à Recarga Dinâmica do .NET para cenários adicionais que normalmente não têm suporte, como alterações de código que exigem a limpeza de um cache ou a atualização da interface do usuário. Por exemplo, para dar suporte à recarga dinâmica com um serializador JSON, você precisa limpar seu cache quando um tipo é modificado. Para desenvolvedores do .NET MAUI, talvez seja necessário estender a recarga dinâmica para edições/atualizações que não disparam o recarregamento em condições normais, como editar um construtor ou um manipulador de eventos para um elemento de interface do usuário. Você pode usar o MetadataUpdateHandlerAttribute para atualizar o estado do aplicativo, disparar uma nova renderização da interface do usuário ou executar ações semelhantes.

O tipo especificado por esse atributo deve implementar métodos estáticos que correspondam à assinatura de um ou mais dos seguintes:

static void ClearCache(Type[]? updatedTypes)
static void UpdateApplication(Type[]? updatedTypes)

ClearCache oferece aos manipuladores de atualização a oportunidade de limpar todos os caches inferidos com base nos metadados do aplicativo. Depois que todos os métodos ClearCache forem invocados, UpdateApplication será invocado para cada manipulador que especifica um. Você pode usar UpdateApplication para atualizar a interface do usuário.

Exemplo

O exemplo a seguir mostra um cenário para um projeto .NET MAUI que inicialmente não dá suporte à recarga dinâmica, mas, em seguida, dá suporte ao recurso após a implementação de MetadataUpdateHandler.

Testar Recarga Dinâmica do .NET

  1. Criar um novo projeto do .NET MAUI no Visual Studio. Escolha o modelo de projeto do aplicativo .NET MAUI.

  2. Em App.xaml.cs, substitua o código para criar o MainPage pelo seguinte código:

    //MainPage = new MainPage(); // Template default code
    MainPage = new NavigationPage(new MainPage());
    

    Em seguida, você implementa um método Build para simplificar uma atualização da interface do usuário em C#. Esse método define o ContentPage.Content e é chamado no OnNavigatedTo da página. O evento OnNavigatedTo deve ser hospedado no Shell ou em uma NavigationPage.

  3. Em MainPage.xaml.cs, substitua o código do construtor MainPage pelo seguinte código:

    public MainPage()
    {
       InitializeComponent();
       Build();
    }
    
    void Build() => Content =
       new Label
       {
          Text = "First line\nSecond line"
       };
    
    protected override void OnNavigatedTo(NavigatedToEventArgs args)
    {
       base.OnNavigatedTo(args);
       Build();
    }
    
  4. Pressione F5 para iniciar o aplicativo.

  5. Depois que a página for carregada, altere o texto do rótulo no código C# para algo como: "Primeira linha\nSegunda linha\nTerceira linha"

  6. Selecione o botão Recarga DinâmicaScreenshot of the Hot Reload button..

    O texto atualizado não é exibido no aplicativo em execução. Não há suporte para Recarga Dinâmica para esse cenário por padrão.

    Screenshot of Hot Reload not working.

Adicionar o MetadataUpdateHandler

Em um aplicativo .NET MAUI, você deve fazer algo para executar novamente o código da interface do usuário do C# depois de fazer uma alteração de código. Se o código da interface do usuário estiver escrito em C#, você poderá usar o método UpdateApplication em MetadataUpdateHandler para recarregar a interface do usuário. Para configurar isso, adicione HotReloadService.cs ao seu aplicativo usando o código a seguir.

#if DEBUG
[assembly: System.Reflection.Metadata.MetadataUpdateHandlerAttribute(typeof(YourAppNamespace.HotReloadService))]
namespace YourAppNamespace { 
    public static class HotReloadService
    {
        #pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
        public static event Action<Type[]?>? UpdateApplicationEvent;
        #pragma warning restore CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

        internal static void ClearCache(Type[]? types) { }
        internal static void UpdateApplication(Type[]? types) {
            UpdateApplicationEvent?.Invoke(types);
        }
    }
}
#endif

Substitua YourAppNamespace pelo namespace da página que você está direcionando.

Agora, com o código anterior adicionado, quando você edita o código dinâmico no Visual Studio, ocorre uma alteração de metadados e o aplicativo despacha o UpdateApplicationEvent. Portanto, você precisa adicionar código para registrar o evento e executar a atualização da interface do usuário.

Observação

Para esse cenário, a Recarga Dinâmica de XAML deve estar habilitada.

Em MainPage.xaml.cs, adicione código para registrar o manipulador de eventos UpdateApplicationEvent no evento OnNavigatedTo.

protected override void OnNavigatedTo(NavigatedToEventArgs args)
    {
        base.OnNavigatedTo(args);

        Build();

#if DEBUG
        HotReloadService.UpdateApplicationEvent += ReloadUI;
#endif
    }

Cancele a assinatura do manipulador de eventos em OnNavigatedFrom e, em seguida, adicione o código para manipular o evento e execute novamente a chamada para Build.

protected override void OnNavigatedFrom(NavigatedFromEventArgs args)
   {
   base.OnNavigatedFrom(args);

#if DEBUG
   HotReloadService.UpdateApplicationEvent -= ReloadUI;
#endif
    }

private void ReloadUI(Type[] obj)
{
   MainThread.BeginInvokeOnMainThread(() =>
   {
      Build();
   });
}

Agora, inicie o aplicativo. Quando você faz uma alteração no texto do rótulo no código C# e pressionar o botão Recarga Dinâmica, a interface do usuário é atualizada.

Screenshot of Hot Reload working.