Skip to content

Commit 6b8ffb0

Browse files
Merge pull request #9418 from MicrosoftDocs/main638246918952036634sync_temp
For protected CLA branch, push strategy should use PR and merge to target branch method to work around git push error
2 parents f541452 + 8648828 commit 6b8ffb0

7 files changed

+231
-74
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
---
2+
title: "Extend .NET Hot Reload"
3+
description: "Learn to use the MetadataUpdateHandler attribute to extend .NET Hot Reload to support additional scenarios."
4+
ms.date: 06/20/2023
5+
ms.topic: conceptual
6+
helpviewer_keywords:
7+
- "Hot reload, MetadataUpdateHandler"
8+
- ".NET Hot Reload, MetadataUpdateHandler"
9+
- "MetadataUpdateHandler for .NET Hot Reload"
10+
author: mikejo5000
11+
ms.author: mikejo
12+
manager: jmartens
13+
ms.technology: vs-ide-debug
14+
monikerRange: '>= vs-2022'
15+
ms.workload:
16+
- "multiple"
17+
---
18+
# Extend .NET Hot Reload using MetadataUpdateHandler (C#, Visual Basic)
19+
20+
[!INCLUDE [Visual Studio](~/includes/applies-to-version/vs-windows-only.md)]
21+
22+
You can programmatically extend .NET Hot Reload support for additional scenarios that aren't typically supported, such as code changes that require clearing a cache or refreshing the UI. For example, to support hot reload with a JSON serializer, you need to clear its cache when a type is modified. For .NET MAUI developers, you may need to extend hot reload for edits/updates that don't trigger hot reload under normal conditions, such as editing a constructor, or an event handler for a UI element. You can use the <xref:System.Reflection.Metadata.MetadataUpdateHandlerAttribute> to refresh the application state, trigger a UI re-render, or perform similar actions.
23+
24+
The type specified by this attribute should implement static methods matching the signature of one or more of the following:
25+
26+
```csharp
27+
static void ClearCache(Type[]? updatedTypes)
28+
static void UpdateApplication(Type[]? updatedTypes)
29+
```
30+
31+
`ClearCache` gives update handlers an opportunity to clear any caches that are inferred based on the application's metadata. After all `ClearCache` methods have been invoked, `UpdateApplication` is invoked for every handler that specifies one. You might use `UpdateApplication` to refresh the UI.
32+
33+
## Example
34+
35+
The following example shows a scenario for a .NET MAUI project that initially does not support hot reload, but then supports the feature after implementing `MetadataUpdateHandler`.
36+
37+
### Test .NET Hot Reload
38+
39+
1. Create a new .NET MAUI project in Visual Studio. Choose the **.NET MAUI App** project template.
40+
41+
1. In *App.xaml.cs*, replace the code to create the MainPage with the following code:
42+
43+
```csharp
44+
//MainPage = new MainPage(); // Template default code
45+
MainPage = new NavigationPage(new MainPage());
46+
```
47+
48+
Next, you implement a Build method to simplify a UI update in C#. This method sets the `ContentPage.Content` and is called in the page's `OnNavigatedTo`. The `OnNavigatedTo` event must be hosted within Shell or a NavigationPage.
49+
50+
1. In *MainPage.xaml.cs*, replace the `MainPage` constructor code with the following code:
51+
52+
```csharp
53+
public MainPage()
54+
{
55+
InitializeComponent();
56+
Build();
57+
}
58+
59+
void Build() => Content =
60+
new Label
61+
{
62+
Text = "First line\nSecond line"
63+
};
64+
65+
protected override void OnNavigatedTo(NavigatedToEventArgs args)
66+
{
67+
base.OnNavigatedTo(args);
68+
Build();
69+
}
70+
```
71+
72+
1. Press **F5** to start the app.
73+
74+
1. After the page loads, change the label text in the C# code to something like: "First line\nSecond line\nThird line"
75+
76+
1. Select the **Hot Reload** ![Screenshot of the Hot Reload button.](../debugger/media/vs-2022/hot-reload-icon.png) button.
77+
78+
The updated text does not display in the running app. There's no Hot Reload support for this scenario by default.
79+
80+
![Screenshot of Hot Reload not working.](../debugger/media/vs-2022/hot-reload-metadataupdatehandler-example.png)
81+
82+
### Add the MetadataUpdateHandler
83+
84+
In a .NET MAUI app, you must do something to re-run C# UI code after you make a code change. If your UI code is written in C#, you could use the `UpdateApplication` method in `MetadataUpdateHandler` to reload the UI. To set this up, add *HotReloadService.cs* to your application using the following code.
85+
86+
```csharp
87+
#if DEBUG
88+
[assembly: System.Reflection.Metadata.MetadataUpdateHandlerAttribute(typeof(YourAppNamespace.HotReloadService))]
89+
namespace YourAppNamespace {
90+
public static class HotReloadService
91+
{
92+
#pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
93+
public static event Action<Type[]?>? UpdateApplicationEvent;
94+
#pragma warning restore CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
95+
96+
internal static void ClearCache(Type[]? types) { }
97+
internal static void UpdateApplication(Type[]? types) {
98+
UpdateApplicationEvent?.Invoke(types);
99+
}
100+
}
101+
}
102+
#endif
103+
```
104+
105+
Make sure you replace `YourAppNamespace` with the namespace for the page you're targeting.
106+
107+
Now, with the preceding code added, when you edit live code in Visual Studio, a metadata change occurs and the app dispatches the `UpdateApplicationEvent`. So, you need to add code to register the event and perform the UI update.
108+
109+
> [!NOTE]
110+
> For this scenario, XAML Hot Reload must be enabled.
111+
112+
In *MainPage.xaml.cs*, add code to register the `UpdateApplicationEvent` event handler in the `OnNavigatedTo` event.
113+
114+
```csharp
115+
protected override void OnNavigatedTo(NavigatedToEventArgs args)
116+
{
117+
base.OnNavigatedTo(args);
118+
119+
Build();
120+
121+
#if DEBUG
122+
HotReloadService.UpdateApplicationEvent += ReloadUI;
123+
#endif
124+
}
125+
```
126+
127+
Unsubscribe the event handler in `OnNavigatedFrom` and then add code to handle the event and re-execute the call to `Build`.
128+
129+
```csharp
130+
protected override void OnNavigatedFrom(NavigatedFromEventArgs args)
131+
{
132+
base.OnNavigatedFrom(args);
133+
134+
#if DEBUG
135+
HotReloadService.UpdateApplicationEvent -= ReloadUI;
136+
#endif
137+
}
138+
139+
private void ReloadUI(Type[] obj)
140+
{
141+
MainThread.BeginInvokeOnMainThread(() =>
142+
{
143+
Build();
144+
});
145+
}
146+
```
147+
148+
Now, start the app. When you make a change to the label text in your C# code and hit the Hot Reload button, the UI gets refreshed!
149+
150+
![Screenshot of Hot Reload working.](../debugger/media/vs-2022/hot-reload-metadataupdatehandler-example-works.png)
151+
152+
## Additional resources
153+
154+
- [C# UI and .NET Hot Reload](https://dev.to/davidortinau/c-ui-and-net-hot-reload-a-match-made-in-net-maui-243f)
155+
- [Supporting Hot Reload in your .NET application](https://www.meziantou.net/supporting-hot-reload-in-your-dotnet-application.htm)
613 Bytes
Loading
Loading
Loading

docs/debugger/toc.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,12 @@
110110
href: mixed-code-and-missing-information-in-the-call-stack-window.md
111111
- name: Live code editing
112112
items:
113-
- name: Hot Reload (.NET/C++)
114-
href: hot-reload.md
113+
- name: Hot Reload
114+
items:
115+
- name: Hot Reload (.NET/C++)
116+
href: hot-reload.md
117+
- name: Extend Hot Reload (.NET)
118+
href: hot-reload-metadataupdatehandler.md
115119
- name: XAML Hot Reload
116120
items:
117121
- name: Write and debug running XAML code
Loading

0 commit comments

Comments
 (0)