共用方式為


使用 MetadataUpdateHandler 擴充 .NET 熱重新載入 (C#、Visual Basic)

您可以以程式方式擴充 .NET 熱重新載入功能支援,以取得通常不支援的其他情境,例如需要清除快取或重新整理 UI 的程式碼變更。 例如,若要支援使用 JSON 序列化程式進行熱重新載入,您必須在修改類型時清除其快取。 針對 .NET MAUI 開發人員,您可能需要針對在正常情況下不會觸發熱重新載入的編輯/更新擴充熱重新載入,例如編輯建構函式或 UI 元素的事件處理常式。 您可以使用 MetadataUpdateHandlerAttribute 來重新整理應用程式狀態、觸發 UI 重新渲染,或執行類似的動作。

此屬性所指定的類型應該實作符合下列一或多個簽章的靜態方法:

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

ClearCache 提供更新處理器一個機會來清除任何根據應用程式中繼資料推斷的快取。 在呼叫完所有 ClearCache 方法之後,會針對指定了方法的每個處理常式呼叫 UpdateApplication。 您可以使用 UpdateApplication 來重新整理 UI。

Example

下列範例顯示 .NET MAUI 專案的案例,該專案一開始不支援熱重新載入,但之後在實作 MetadataUpdateHandler之後支援此功能。

測試 .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 必須裝載在 Shell 或 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# 程式碼中的標籤文字變更為:「第一行\n第二行\n第三行」

  6. 選取 [熱重新載入] 按鈕Screenshot of the Hot Reload button.的螢幕擷取畫面。

    更新的文字不會顯示在執行中的應用程式中。 根據預設,此情境沒有即時重新載入支援。

    熱重載不起作用的螢幕截圖。

新增 MetadataUpdateHandler

在 .NET MAUI 應用程式中,您必須執行某些動作,才能在進行程式代碼變更之後重新執行 C# UI 程式代碼。 如果您的 UI 程式碼是以 C# 撰寫,您可以使用 UpdateApplication 方法在 MetadataUpdateHandler 中重新載入 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 更新。

備註

在此案例中,必須啟用 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# 程式碼中的標籤文字並按下 [熱重新載入] 按鈕時,使用者介面會重新整理!

熱重載工作的螢幕截圖。