using CommunityToolkit.Mvvm.Messaging; using Microsoft.Extensions.DependencyInjection; namespace Toolkit.Foundation; public class NavigateHandler(Scoped scoped, IScopedServiceProvider scopedServiceProvider) : IHandler { public void Handle(NavigateEventArgs args) { object? region = args.Region; string route = args.Route; IDictionary? parameters = null; object? sender = args.Sender; string[] segments = route.Split('/'); object? resolvedRegion = region is "self" ? "self" : null; IServiceProvider? serviceProvider = null; INavigationRegionProvider? navigationRegionProvider = null; IServiceFactory? serviceFactory = null; IMessenger? messenger = null; if (resolvedRegion is null && region is not null) { if (args.Sender is IServiceProviderRequired requireServiceProvider) { if (args.Scope is NavigateScope.Scoped) { serviceProvider = requireServiceProvider.Provider; serviceFactory = requireServiceProvider.Provider.GetRequiredService(); navigationRegionProvider = requireServiceProvider.Provider.GetRequiredService(); messenger = requireServiceProvider.Provider.GetRequiredService(); } if (args.Scope is NavigateScope.CreateScope) { IServiceScope serviceScope = requireServiceProvider.Provider.CreateScope(); serviceProvider = serviceScope.ServiceProvider; serviceFactory = serviceScope.ServiceProvider.GetRequiredService(); navigationRegionProvider = serviceScope.ServiceProvider.GetRequiredService(); messenger = requireServiceProvider.Provider.GetRequiredService(); } if (navigationRegionProvider is not null) { if (navigationRegionProvider.TryGet(region, out object? value)) { resolvedRegion = value; } } } if (scopedServiceProvider.TryGet(scoped, out IServiceProvider? scopedProvider)) { serviceProvider ??= scopedProvider; serviceFactory ??= scopedProvider?.GetRequiredService(); messenger ??= scopedProvider?.GetRequiredService(); if (resolvedRegion is null) { navigationRegionProvider = scopedProvider?.GetRequiredService(); if (navigationRegionProvider is not null) { if (navigationRegionProvider.TryGet(region, out object? value)) { resolvedRegion = value; } } } } } if (resolvedRegion is not null && serviceProvider is not null && serviceFactory is not null && messenger is not null) { Dictionary? arguments = parameters?.ToDictionary(x => x.Key, x => x.Value, StringComparer.InvariantCultureIgnoreCase) ?? []; foreach (object segment in segments) { if (serviceProvider.GetRequiredKeyedService(segment) is IContentTemplateDescriptor descriptor) { if (serviceProvider.GetRequiredKeyedService(descriptor.TemplateType, descriptor.Key) is object template) { object?[] resolvedArguments = parameters is not null ? descriptor.ContentType .GetConstructors() .FirstOrDefault()? .GetParameters() .Select(x => x?.Name is not null && arguments is not null && arguments.TryGetValue(x.Name, out object? argument) ? argument : null) .Where(argument => argument is not null) .ToArray() ?? [] : []; object? content = resolvedArguments is { Length: > 0 } ? serviceFactory.Create(descriptor.ContentType, parameters) : serviceProvider.GetRequiredKeyedService(descriptor.ContentType, descriptor.Key); messenger.Send(new NavigateTemplateEventArgs(resolvedRegion, template, content, sender, parameters), resolvedRegion is string ? $"{resolvedRegion}" : resolvedRegion.GetType().Name); } } } } } }