Skip to content
This repository was archived by the owner on Feb 16, 2023. It is now read-only.

Enhanced APIs #24

Merged
merged 6 commits into from
May 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 71 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,87 @@
# Prism.Maui

Prism for .NET MAUI is more than simply a port of Prism for Xamarin.Forms. Many of the features remain largely untouched, however the codebase has been written specifically for MAUI. For existing Prism platforms, PrismApplication is responsible for a lot of service registration. Maui presents a very different paradigm to the app startup process as it uses the AppHostBuilder pattern that you may be familiar with from AspNetCore and other .NET Core applications. Due to the fact that services are registered as part of the MauiAppBuilder bootstrapping, the application bootstrapping that you would typically find as part of the PrismApplication is now instead part of PrismAppBuilder.

As part of this rewrite, some attention to making it easier for legacy Xamarin.Forms apps to be ported to MAUI has been given. In general however, this has been written with specific attention to the updated application initialization patterns that we see with .NET MAUI.

## Support

Please help support Prism and Prism.Maui by becoming a GitHub Sponsor. The work on Prism.Maui is NOT funded by any entity and is done entirely in my spare time. Your financial contributions help support my efforts to provide the best possible experience for the community.

## Using Prism.Maui

To help follow MAUI's App Builder pattern we have introduced the `UsePrism<TApp>` extension on the `MauiAppBuilder`. This will create a `PrismAppBuilder` which gives you specific access to various methods you may want for initializing your application.

```cs
// OOB Maui Application
MauiApp.CreateBuilder()
.UseMauiApp<App>();

// Prism.Maui
PrismApp.CreateBuilder()
.RegisterServices(containerRegistry => {
containerRegistry.RegisterForNavigation<MainPage>();
})
.ConfigureModuleCatalog(catalog => {
catalog.AddModule<AuthModule>();
})
MauiApp.CreateBuilder()
.UsePrismApp<App>();
```

## Service Registration
Some of the methods available on the `PrismAppBuilder` are going to seem a bit familiar for developers coming from Prism for Xamarin.Forms such as:

```cs
MauiApp.CreateBuilder()
.UsePrismApp<App>()
.RegisterServices(container => {
container.Register<ISomeService, SomeImplementation>();
container.RegisterForNavigation<ViewA, ViewAViewModel>();
}
.ConfigureModuleCatalog(catalog => {
catalog.AddModule<ModuleA>();
});
.OnInitialized(() => {
// Do some initializations here
});
```

You will find that this includes useful extensions that consider that you are wiring up these initializations as part of the App Builder. A common case would be where you may have used the container in PrismApplication in the past, you now have an overload that provides the use of the Container.

```cs
MauiApp.CreateBuilder()
.UsePrismApp<App>()
.OnInitialized(container => {
var foo = container.Resolve<IFoo>();
// Do some initializations here
});
```

The `PrismAppBuilder` additionally provides some new things to make your life easier.

```cs
MauiApp.CreateBuilder()
.UsePrismApp<App>()
.OnAppStart(async navigationService =>
{
var result = await navigationService.NavigateAsync("MainPage/NavigationPage/ViewA");
if (!result.Success)
{
System.Diagnostics.Debugger.Break();
}
});
```

### Microsoft Extensions Support

To help make it even easier we have added some special extensions to the `PrismAppBuilder` that will make it easier to use Microsoft Extensions. This includes the `ConfigureLogging` method to make it easier to setup your logging while still using the `PrismAppBuilder`. For those who prefer to use `IServiceCollection` to manage their registrations, you can additionally use the `ConfigureServices` extension and bypass the normal Prism `RegisterServices` method.

```cs
MauiApp.CreateBuilder()
.UsePrismApp<App>()
.ConfigureServices(services => {
services.AddSingleton<IFoo, Foo>();
services.RegisterForNavigation<ViewA, ViewAViewModel>();
});
```

For existing Prism platforms, PrismApplication is responsible for a lot of service registration. Maui presents a very different paradigm to the app startup process as it uses the AppHostBuilder pattern that you may be familiar with from AspNetCore and other .NET Core applications. Due to the fact that services are registered as part of the MauiAppBuilder bootstrapping, the application bootstrapping that you would typically find as part of the PrismApplication is now instead part of PrismAppBuilder. This App Builder provides the typical PrismApplication bootstrapping, while returning the MauiAppBuilder when you call UsePrismApp to allow you to continue to configure your app like any other Maui Application.
## Upgrading from Prism.Forms

For those items such as Pages registered for Navigation which need to be registered with the Prism Container Abstraction, you can register them with the RegisterServices extension off of the PrismAppBuilder. Similarly you can call ConfigureModuleCatalog to register modules or provide delegate to execute as part of the container initialization. Note that these will run prior to the Maui services being registered or the finial container being ready to use.
PrismApplication is largely obsolete for Prism.Maui. The PrismAppBuilder does not have an explicit requirement on it. To make it easier on those who are upgrading, we do have legacy support methods to make updating your existing apps a little easier. This includes a `RegisterTypes` & `OnInitialized` method which will get called during the app initialization. It is recommended however that you migrate this code to your App Builder.

## NOTE

Prism.Maui is current an experimental Alpha. Any preview build is largely meant to solicit additional developer feedback. APIs will likely change and break prior to being merged into the Prism repo and released as a fully official build.
Prism.Maui is current an experimental Alpha. Any preview build is largely meant to solicit additional developer feedback. APIs will likely change and break prior to being merged into the Prism repo and released as a fully official build.
4 changes: 1 addition & 3 deletions sample/PrismMauiDemo/MauiProgram.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using MauiModule;
using MauiModule;
using Prism;
using Prism.Ioc;
using Prism.Modularity;
Expand All @@ -21,8 +21,6 @@ public static MauiApp CreateMauiApp()
{
containerRegistry.RegisterForNavigation<MainPage>();
containerRegistry.RegisterForNavigation<SamplePage>();
containerRegistry.RegisterForNavigation<NavigationPage>();
containerRegistry.RegisterForNavigation<TabbedPage>();
})
.OnAppStart(async navigationService =>
{
Expand Down
28 changes: 27 additions & 1 deletion src/Prism.Maui/Ioc/MicrosoftDependencyInjectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Prism.Ioc;
using Prism.Navigation;

namespace Prism.Ioc;

public static class MicrosoftDependencyInjectionExtensions
{
Expand All @@ -17,4 +19,28 @@ public static IServiceProvider CreateServiceProvider(this IContainerExtension co

return sca.CreateServiceProvider();
}

public static IServiceCollection RegisterForNavigation<TView>(this IServiceCollection services, string name = null)
where TView : Page =>
services.RegisterForNavigation(typeof(TView), null, name);

public static IServiceCollection RegisterForNavigation<TView, TViewModel>(this IServiceCollection services, string name = null)
where TView : Page =>
services.RegisterForNavigation(typeof(TView), typeof(TViewModel), name);

public static IServiceCollection RegisterForNavigation(this IServiceCollection services, Type view, Type viewModel, string name = null)
{
if (view is null)
throw new ArgumentNullException(nameof(view));

if (string.IsNullOrEmpty(name))
name = view.Name;

NavigationRegistry.Register(view, viewModel, name);
services.AddTransient(view);

if (viewModel != null)
services.AddTransient(viewModel);
return services;
}
}
11 changes: 8 additions & 3 deletions src/Prism.Maui/PrismAppBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public abstract class PrismAppBuilder
private List<Action<IContainerRegistry>> _registrations { get; }
private List<Action<IContainerProvider>> _initializations { get; }
private IContainerProvider _container { get; }
private Action<INavigationService> _onAppStarted;
private Action<IContainerProvider, INavigationService> _onAppStarted;

protected PrismAppBuilder(IContainerExtension containerExtension, MauiAppBuilder builder)
{
Expand Down Expand Up @@ -104,14 +104,19 @@ internal void OnInitialized()
}

var app = _container.Resolve<IApplication>();
if (NavigationRegistry.GetPageType(nameof(NavigationPage)) is null)
((IContainerRegistry)_container).RegisterForNavigation<NavigationPage>();
if (NavigationRegistry.GetPageType(nameof(TabbedPage)) is null)
((IContainerRegistry)_container).RegisterForNavigation<TabbedPage>();

if (app is ILegacyPrismApplication prismApp)
prismApp.OnInitialized();

if (_onAppStarted is not null)
_onAppStarted(_container.Resolve<INavigationService>());
_onAppStarted(_container, _container.Resolve<INavigationService>());
}

public MauiAppBuilder OnAppStart(Action<INavigationService> onAppStarted)
public MauiAppBuilder OnAppStart(Action<IContainerProvider, INavigationService> onAppStarted)
{
_onAppStarted = onAppStarted;
return MauiBuilder;
Expand Down
29 changes: 24 additions & 5 deletions src/Prism.Maui/PrismAppBuilderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui;
using Microsoft.Maui.Hosting;
using Prism.Ioc;
using Prism.Ioc;
using Prism.Modularity;
using Prism.Mvvm;
using Prism.Navigation;
using Microsoft.Extensions.Logging;

namespace Prism;

Expand Down Expand Up @@ -43,4 +41,25 @@ public static PrismAppBuilder ConfigureModuleCatalog(this PrismAppBuilder builde
configureCatalog(moduleCatalog);
});
}

public static MauiAppBuilder OnAppStart(this PrismAppBuilder builder, Action<INavigationService> onAppStarted) =>
builder.OnAppStart((_, n) => onAppStarted(n));

public static MauiAppBuilder OnAppStart(this PrismAppBuilder builder, Func<IContainerProvider, INavigationService, Task> onAppStarted) =>
builder.OnAppStart(async (c, n) => await onAppStarted(c, n));

public static MauiAppBuilder OnAppStart(this PrismAppBuilder builder, Func<INavigationService, Task> onAppStarted) =>
builder.OnAppStart(async (_, n) => await onAppStarted(n));

public static PrismAppBuilder ConfigureServices(this PrismAppBuilder builder, Action<IServiceCollection> configureServices)
{
configureServices(builder.MauiBuilder.Services);
return builder;
}

public static PrismAppBuilder ConfigureLogging(this PrismAppBuilder builder, Action<ILoggingBuilder> configureLogging)
{
configureLogging(builder.MauiBuilder.Logging);
return builder;
}
}
3 changes: 3 additions & 0 deletions src/Prism.Maui/PrismApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public abstract class PrismApplication : Application, ILegacyPrismApplication
protected PrismApplication()
{
_containerExtension = ContainerLocator.Current;
RegisterTypes(_containerExtension);
NavigationService = Container.Resolve<INavigationService>((typeof(IApplication), this));
}

Expand All @@ -27,6 +28,8 @@ protected PrismApplication()
// Provided to better support legacy apps updating from Prism.Forms
protected virtual void OnInitialized() { }

protected virtual void RegisterTypes(IContainerRegistry containerRegistry) { }

protected sealed override Window CreateWindow(IActivationState activationState) =>
this.GetDefaultPrismWindow();
}
4 changes: 4 additions & 0 deletions src/Prism.Maui/build/Prism.Maui.targets
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
<Project>
<ItemGroup>
<Using Include="Prism" />
<Using Include="Prism.AppModel" />
<Using Include="Prism.Commands" />
<Using Include="Prism.Events" />
<Using Include="Prism.Ioc" />
<Using Include="Prism.Modularity" />
<Using Include="Prism.Mvvm" />
<Using Include="Prism.Navigation" />
<Using Include="Prism.Services" />
</ItemGroup>
</Project>