Share via


MetadataUpdateHandler を使用して .NET ホット リロードを拡張する (C#、Visual Basic)

キャッシュのクリアや UI の更新を必要とするコード変更など、通常サポートされていない追加のシナリオに対して、.NET ホット リロード サポートをプログラムによって拡張できます。 たとえば、JSON シリアライザーでホット リロードをサポートするには、型が変更されたときにそのキャッシュをクリアする必要があります。 .NET MAUI 開発者のために、コンストラクターの編集や UI 要素のイベント ハンドラーなど、通常の条件下でホット リロードをトリガーしない編集/更新に対してホット リロードを拡張することが必要になる場合があります。 MetadataUpdateHandlerAttribute を使用して、アプリケーションの状態の更新、UI の再レンダリングのトリガー、または同様のアクションの実行を行うことができます。

この属性で指定される型は、次に示すシグネチャの 1 つ以上に一致する静的メソッドを実装する必要があります。

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

ClearCache は、更新ハンドラーに、アプリケーションのメタデータに基づいて推論されたすべてのキャッシュをクリアする機会を与えます。 すべての ClearCache メソッドが呼び出された後、UpdateApplication が、これを指定するすべてのハンドラーに対して呼び出されます。 UpdateApplication を使用して UI を更新できます。

次の例に示すのは、最初はホット リロードをサポートしておらず、MetadataUpdateHandler の実装後にこの機能をサポートするようになる .NET MAUI プロジェクトのシナリオです。

.NET ホット リロードをテストする

  1. Visual Studio で新しい .NET MAUI プロジェクトを作成します。 .NET MAUI アプリ プロジェクト テンプレートを選択します。

  2. App.xaml.cs で、MainPage を作成するコードを次のコードで置き換えます。

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

    次に、Build メソッドを実装して C# での UI の更新を簡略化します。 このメソッドは、ContentPage.Content を設定し、ページの OnNavigatedTo で呼び出されます。 OnNavigatedTo イベントは、シェルまたは NavigationPage 内でホストされている必要があります。

  3. MainPage.xaml.cs で、MainPage コンストラクター コードを次のコードで置き換えます。

    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. F5 キーを押してアプリを起動します。

  5. ページが読み込まれたら、C# コードのラベル テキストを "1 行目\n2 行目\n3 行目" などに変更します

  6. [ホット リロード]Screenshot of the Hot Reload button. ボタンを選択します。

    更新されたテキストは、実行中のアプリには表示されません。 既定では、このシナリオに対するホット リロード サポートはありません。

    Screenshot of Hot Reload not working.

MetadataUpdateHandler を追加する

.NET MAUI アプリでは、コードを変更した後に C# UI コードを再実行するために行うべきことがあります。 UI コードが C# で記述されている場合は、MetadataUpdateHandlerUpdateApplication メソッドを使用して UI を再読み込みできます。 これを設定するには、次のコードを使用して HotReloadService.cs をアプリケーションに追加します。

#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

YourAppNamespace を対象としているページの名前空間で置き換えるようにしてください。

先述のコードが追加されたので、Visual Studio でライブ コードを編集すると、メタデータの変更が発生し、アプリによって UpdateApplicationEvent がディスパッチされます。 そのため、イベントを登録して UI 更新を実行するコードを追加する必要があります。

Note

このシナリオでは、XAML ホット リロードを有効にする必要があります。

MainPage.xaml.cs で、OnNavigatedTo イベントに UpdateApplicationEvent イベント ハンドラーを登録するコードを追加します。

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

        Build();

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

OnNavigatedFrom でイベント ハンドラーの登録を解除してから、イベントを処理するコードを追加し、Build の呼び出しを再実行します。

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

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

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

アプリを起動します。 C# コードのラベル テキストに変更を行い、[ホット リロード] ボタンをクリックすると、UI が更新されます。

Screenshot of Hot Reload working.