-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added ViewModel paramater resolution, bump remaining projects to .NET 8
- Loading branch information
1 parent
85a7212
commit c2315fd
Showing
5 changed files
with
117 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,63 +1,105 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Maui.Controls; | ||
using System; | ||
using System.Threading.Tasks; | ||
|
||
namespace Maui.Plugins.PageResolver | ||
namespace Maui.Plugins.PageResolver; | ||
|
||
public static class NavigationExtensions | ||
{ | ||
public static class NavigationExtensions | ||
#region paramaterless navigation | ||
|
||
/// <summary> | ||
/// Resolves a page of type T (must inherit from Page) and pushes a new instance onto the navigation stack | ||
/// </summary> | ||
/// <typeparam name="T"></typeparam> | ||
/// <param name="navigation"></param> | ||
/// <returns></returns> | ||
public static async Task PushAsync<T>(this INavigation navigation) where T : Page | ||
{ | ||
/// <summary> | ||
/// Resolves a page of type T (must inherit from Page) and pushes a new instance onto the navigation stack | ||
/// </summary> | ||
/// <typeparam name="T"></typeparam> | ||
/// <param name="navigation"></param> | ||
/// <returns></returns> | ||
public static async Task PushAsync<T>(this INavigation navigation) where T : Page | ||
{ | ||
var resolvedPage = Resolver.Resolve<T>(); | ||
var resolvedPage = Resolver.Resolve<T>(); | ||
|
||
await navigation.PushAsync(resolvedPage); | ||
} | ||
await navigation.PushAsync(resolvedPage); | ||
} | ||
|
||
/// <summary> | ||
/// Resolves a page of type T (must inherit from Page) and pushes a new instance onto the navigation stack | ||
/// </summary> | ||
/// <typeparam name="T">The type of the page to be resolved</typeparam> | ||
/// <param name="navigation"></param> | ||
/// <param name="parameters">The constructor parameters expected by the page to be resolved</param> | ||
/// <returns></returns> | ||
public static async Task PushAsync<T>(this INavigation navigation, params object[] parameters) where T : Page | ||
{ | ||
var resolvedPage = ActivatorUtilities.CreateInstance<T>(Resolver.GetServiceProvider(), parameters); | ||
/// <summary> | ||
/// Resolves a page of type T (must inherit from Page) and pushes a new modal instance onto the navigation stack | ||
/// </summary> | ||
/// <typeparam name="T"></typeparam> | ||
/// <param name="navigation"></param> | ||
/// <returns></returns> | ||
public static async Task PushModalAsync<T>(this INavigation navigation) where T : Page | ||
{ | ||
var resolvedPage = Resolver.Resolve<T>(); | ||
|
||
await navigation.PushAsync(resolvedPage); | ||
} | ||
await navigation.PushModalAsync(resolvedPage); | ||
} | ||
|
||
#endregion | ||
|
||
/// <summary> | ||
/// Resolves a page of type T (must inherit from Page) and pushes a new modal instance onto the navigation stack | ||
/// </summary> | ||
/// <typeparam name="T"></typeparam> | ||
/// <param name="navigation"></param> | ||
/// <returns></returns> | ||
public static async Task PushModalAsync<T>(this INavigation navigation) where T : Page | ||
{ | ||
var resolvedPage = Resolver.Resolve<T>(); | ||
|
||
await navigation.PushModalAsync(resolvedPage); | ||
#region parameterized navigation | ||
|
||
/// <summary> | ||
/// Resolves a page of type T (must inherit from Page) and pushes a new instance onto the navigation stack | ||
/// </summary> | ||
/// <typeparam name="T">The type of the page to be resolved</typeparam> | ||
/// <param name="navigation"></param> | ||
/// <param name="parameters">The constructor parameters expected by the page to be resolved</param> | ||
/// <returns></returns> | ||
public static async Task PushAsync<T>(this INavigation navigation, params object[] parameters) where T : Page | ||
{ | ||
var page = ResolvePage<T>(parameters); | ||
await navigation.PushAsync(page); | ||
} | ||
|
||
/// <summary> | ||
/// Resolves a page of type T (must inherit from Page) and pushes a new modal instance onto the navigation stack | ||
/// </summary> | ||
/// <typeparam name="T">The type of the page to be resolved</typeparam> | ||
/// <param name="navigation"></param> | ||
/// <param name="parameters">The constructor parameters expected by the page to be resolved</param> | ||
/// <returns></returns> | ||
public static async Task PushModalAsync<T>(this INavigation navigation, params object[] parameters) where T : Page | ||
{ | ||
var page = ResolvePage<T>(parameters); | ||
await navigation.PushModalAsync(page); | ||
} | ||
|
||
|
||
private static Page ResolvePage<T>(params object[] parameters) where T : Page | ||
{ | ||
var serviceProvider = Resolver.GetServiceProvider(); | ||
|
||
// Try to get the ViewModel type. | ||
var viewModelType = Type.GetType($"{typeof(T).FullName}ViewModel"); | ||
if (viewModelType == null) | ||
{ | ||
return CreatePageWithoutViewModel<T>(serviceProvider, parameters); | ||
} | ||
|
||
/// <summary> | ||
/// Resolves a page of type T (must inherit from Page) and pushes a new modal instance onto the navigation stack | ||
/// </summary> | ||
/// <typeparam name="T">The type of the page to be resolved</typeparam> | ||
/// <param name="navigation"></param> | ||
/// <param name="parameters">The constructor parameters expected by the page to be resolved</param> | ||
/// <returns></returns> | ||
public static async Task PushModalAsync<T>(this INavigation navigation, params object[] parameters) where T : Page | ||
return CreatePageWithViewModel<T>(serviceProvider, viewModelType, parameters); | ||
} | ||
|
||
private static Page CreatePageWithoutViewModel<T>(IServiceProvider serviceProvider, params object[] parameters) where T : Page | ||
{ | ||
return ActivatorUtilities.CreateInstance<T>(serviceProvider, typeof(T), parameters); | ||
} | ||
|
||
private static Page CreatePageWithViewModel<T>(IServiceProvider serviceProvider, Type viewModelType, params object[] parameters) where T : Page | ||
{ | ||
var viewModel = ActivatorUtilities.CreateInstance(serviceProvider, viewModelType, parameters); | ||
|
||
using (var scope = serviceProvider.CreateScope()) | ||
{ | ||
var resolvedPage = ActivatorUtilities.CreateInstance<T>(Resolver.GetServiceProvider(), parameters); | ||
var scopedServiceProvider = scope.ServiceProvider; | ||
var serviceCollection = new ServiceCollection(); | ||
serviceCollection.AddSingleton(viewModelType, viewModel); | ||
var scopedProvider = serviceCollection.BuildServiceProvider(); | ||
|
||
await navigation.PushModalAsync(resolvedPage); | ||
return ActivatorUtilities.CreateInstance<T>(scopedProvider, typeof(T)); | ||
} | ||
} | ||
|
||
#endregion | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,35 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using System; | ||
|
||
namespace Maui.Plugins.PageResolver | ||
namespace Maui.Plugins.PageResolver; | ||
|
||
public static class Resolver | ||
{ | ||
public static class Resolver | ||
{ | ||
private static IServiceScope scope; | ||
private static IServiceScope scope; | ||
|
||
/// <summary> | ||
/// Registers the service provider and creates a dependency scope | ||
/// </summary> | ||
/// <param name="sp"></param> | ||
internal static void RegisterServiceProvider(IServiceProvider sp) | ||
{ | ||
scope ??= sp.CreateScope(); | ||
} | ||
/// <summary> | ||
/// Registers the service provider and creates a dependency scope | ||
/// </summary> | ||
/// <param name="sp"></param> | ||
internal static void RegisterServiceProvider(IServiceProvider sp) | ||
{ | ||
scope ??= sp.CreateScope(); | ||
} | ||
|
||
/// <summary> | ||
/// Returns a resolved instance of the requested type. | ||
/// </summary> | ||
/// <typeparam name="T"></typeparam> | ||
/// <returns></returns> | ||
internal static T Resolve<T>() where T : class | ||
{ | ||
var result = scope.ServiceProvider.GetRequiredService<T>(); | ||
/// <summary> | ||
/// Returns a resolved instance of the requested type. | ||
/// </summary> | ||
/// <typeparam name="T"></typeparam> | ||
/// <returns></returns> | ||
internal static T Resolve<T>() where T : class | ||
{ | ||
var result = scope.ServiceProvider.GetRequiredService<T>(); | ||
|
||
return result; | ||
} | ||
return result; | ||
} | ||
|
||
internal static IServiceProvider GetServiceProvider() | ||
{ | ||
return scope.ServiceProvider; | ||
} | ||
internal static IServiceProvider GetServiceProvider() | ||
{ | ||
return scope.ServiceProvider; | ||
} | ||
} |