From a14bbc46d71ab9485bb2f48b0cc098a3b64f2740 Mon Sep 17 00:00:00 2001 From: Oleksandr Liakhevych Date: Fri, 29 Apr 2022 00:47:50 +0300 Subject: [PATCH] Create service scopes for navigated pages --- .../ShellNavigation/ShellNavigationManager.cs | 33 +++++++------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/src/Microsoft.MobileBlazorBindings/ShellNavigation/ShellNavigationManager.cs b/src/Microsoft.MobileBlazorBindings/ShellNavigation/ShellNavigationManager.cs index 7e1c867..7a8af86 100644 --- a/src/Microsoft.MobileBlazorBindings/ShellNavigation/ShellNavigationManager.cs +++ b/src/Microsoft.MobileBlazorBindings/ShellNavigation/ShellNavigationManager.cs @@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Components; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; using Microsoft.MobileBlazorBindings.Elements.Handlers; using Microsoft.MobileBlazorBindings.ShellNavigation; using System; @@ -101,12 +100,15 @@ namespace Microsoft.MobileBlazorBindings internal async Task BuildPage(Type componentType) { +#pragma warning disable CA2000 // Dispose objects before losing scope. Scope is disposed when page is closed. + var scope = _services.CreateScope(); +#pragma warning restore CA2000 // Dispose objects before losing scope + var serviceProvider = scope.ServiceProvider; + var container = new RootContainerHandler(); var route = NavigationParameters[componentType]; -#pragma warning disable CA2000 // Dispose objects before losing scope. Renderer is disposed when page is closed. - var renderer = new MobileBlazorBindingsRenderer(_services, _services.GetRequiredService()); -#pragma warning restore CA2000 // Dispose objects before losing scope + var renderer = serviceProvider.GetRequiredService(); var convertedParameters = ConvertParameters(componentType, route.Parameters); var addComponentTask = renderer.AddComponent(componentType, container, convertedParameters); @@ -122,29 +124,16 @@ namespace Microsoft.MobileBlazorBindings var page = container.Elements.FirstOrDefault() as MC.Page ?? throw new InvalidOperationException("The target component of a Shell navigation must derive from the Page component."); - DisposeRendererWhenPageIsClosed(renderer, page); + page.ParentChanged += DisposeScopeWhenParentRemoved; return page; - } - private void DisposeRendererWhenPageIsClosed(MobileBlazorBindingsRenderer renderer, MC.Page page) - { - // Unfortunately, XF does not expose any Destroyed event for elements. - // Therefore we subscribe to Navigated event, and consider page as destroyed - // if it is not present in the navigation stack. - MC.Shell.Current.Navigated += DisposeWhenNavigatedAway; - - void DisposeWhenNavigatedAway(object sender, MC.ShellNavigatedEventArgs args) + void DisposeScopeWhenParentRemoved(object _, EventArgs __) { - // We need to check all navigationStacks for all Shell items. - var currentPages = MC.Shell.Current.Items - .SelectMany(i => i.Items) - .SelectMany(i => i.Navigation.NavigationStack); - - if (!currentPages.Contains(page)) + if (page.Parent is null) { - MC.Shell.Current.Navigated -= DisposeWhenNavigatedAway; - renderer.Dispose(); + scope.Dispose(); + page.ParentChanged -= DisposeScopeWhenParentRemoved; } } }