-
Notifications
You must be signed in to change notification settings - Fork 49
Expand file tree
/
Copy pathUserMainPage.razor
More file actions
91 lines (79 loc) · 3.16 KB
/
UserMainPage.razor
File metadata and controls
91 lines (79 loc) · 3.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
@page "/__main"
@using Microsoft.JSInterop
@using System.Runtime.Loader
@using Try.UserComponents
@using TryMudBlazor.Client.Services
@inject IJSRuntime JSRuntime
@inject UserComponentsAssemblyService AssemblyService
@implements IAsyncDisposable
<MudDialogProvider FullWidth="true" MaxWidth="MaxWidth.ExtraSmall" />
<MudSnackbarProvider />
<DynamicComponent Type="@_type" />
@code {
private Type _type = typeof(__Main);
private AssemblyLoadContext _loadContext;
private readonly Lazy<DotNetObjectReference<UserMainPage>> _ref;
public UserMainPage()
{
_ref = new Lazy<DotNetObjectReference<UserMainPage>>(CreateDotNetObject());
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSRuntime.InvokeVoidAsync("Try.registerHotReload", _ref.Value);
}
}
[JSInvokable]
public async Task HotReload()
{
try
{
var base64 = await JSRuntime.InvokeAsync<string>("sessionStorage.getItem", "TryMudBlazor.UserComponentsDllBase64");
if (base64 == null)
{
// sessionStorage was cleared (e.g. crash recovery) — fall back to a full reload
// so loadBootResource picks up the safe static DLL.
await JSRuntime.InvokeVoidAsync("Try.requestFullReload", "/__main");
return;
}
var bytes = Convert.FromBase64String(base64);
// Swap to a fresh collectible context; previous one becomes eligible for GC
// once Blazor disposes the old component instance below.
var previousContext = _loadContext;
_loadContext = new AssemblyLoadContext(name: null, isCollectible: true);
var assembly = _loadContext.LoadFromStream(new MemoryStream(bytes));
previousContext?.Unload();
// UserStartup requires DI re-registration — fall back to full iframe reload
if (assembly.GetType("UserStartup") is not null ||
assembly.GetType("Try.UserComponents.UserStartup") is not null)
{
await JSRuntime.InvokeVoidAsync("Try.requestFullReload", "/__main");
return;
}
var newType = assembly.GetType("Try.UserComponents.__Main");
if (newType is not null)
{
// Update the Router's AdditionalAssemblies before rendering the new __Main
// so that any NavigateTo calls inside it can resolve user-defined @page routes.
await AssemblyService.UpdateAssemblyAsync(assembly);
_type = newType;
await InvokeAsync(StateHasChanged);
}
}
catch
{
await JSRuntime.InvokeVoidAsync("Try.requestFullReload", "/__main");
}
}
public async ValueTask DisposeAsync()
{
if (_ref.IsValueCreated)
{
await JSRuntime.InvokeVoidAsync("Try.unregisterHotReload");
_ref.Value.Dispose();
}
_loadContext?.Unload();
}
private DotNetObjectReference<UserMainPage> CreateDotNetObject() => DotNetObjectReference.Create(this);
}