Host registration
MVVMExpress uses Microsoft.Extensions.DependencyInjection only. There is no DryIoc, Unity, or Grace package. Shared libraries and tests call AddMvvmExpress. A MAUI app calls UseMvvmExpress, which registers Core services, replaces IMainThread with MauiMainThread, marshals command/property notifications, and auto-attaches ViewModelLifecycleBehavior.
builder
.UseMauiApp<App>()
.UseMvvmExpress(o => o
.UseNavigationPage()
.UseDialogs()
.UseAuth<LoginViewModel>());
// optional catalog path:
// .UseMvvmExpress(o => o.UseShell().UseDialogs().UseAuth<LoginViewModel>());
// net10.0 tests / shared ViewModel projects
services.AddMvvmExpress();
services.AddAuth<LoginViewModel>();UseNavigationPage is the login → replace-root → push host. UseShell is an equal host. UseDialogs lives in the Dialogs package. UseDeepLinks / UseSecureSessionAuth are optional host adapters (fail closed). AddModule<T>() registers a feature assembly. MvvmExpressOptions also has CancelOperationsOnDisappear, EnableDiagnostics, MarshalNotifications (default true), AutoAttachLifecycle, ConfirmDirtyNavigation, ForwardNavigationFailures, and ApplyGeneratedRegistrations. Call InitializeComponent() on App before resolving pages. Do not mix MAUI MainThread statics in ViewModels.
What AddMvvmExpress registers
| Abstraction | Default | Typical app replacement |
|---|---|---|
| IMessageHub | MessageHub | Keep |
| IBusyGate | BusyGate | Keep |
| IErrorSink | NullErrorSink | App logger sink |
| ICache / ICachedFetcher | MemoryCache / CachedFetcher | Plugin.Maui.ApiCache adapter |
| IConnectivityProbe | InMemoryConnectivityProbe | Plugin.Maui.NetworkMonitor adapter |
| IOperationExecutor | OperationExecutor | Keep |
| IViewModelScopeFactory | ServiceViewModelScopeFactory | Keep |
| IFeatureSwitch | MemoryFeatureSwitch | Plugin.Maui.FeatureFlags adapter |
| IStateStore | MemoryStateStore | App persist store |
| IWindowContext | WindowContext.Default | MauiWindowContext.Current |
| IWindowNavigatorRegistry | WindowNavigatorRegistry | Keep; register per window |
| INavigator / IPageNavigator | InMemoryNavigator | UseNavigationPage() / UseShell() |
| IMainThread | ImmediateMainThread | MauiMainThread (host) |
| IDialogs / INotifier | NullDialogs | UseDialogs() → MauiDialogs / MauiNotifier |
| IAuthState | not registered | UseAuth + UseSecureSessionAuth() |
| IAccountService | not registered | App register / reset adapter |
Replace defaults in the MAUI host
UseNavigationPage / UseDialogs replace the in-memory defaults. UseAuth<TChallenge>() wraps GuardedNavigator when screens require a session — do not RemoveAll and reconstruct the guard. UseSecureSessionAuth() and UseDeepLinks() fail closed if the sibling package is missing. Do not register UseShell and UseNavigationPage together unless you really have two hosts.
builder.UseMvvmExpress(o => o
.UseNavigationPage((nav, _) => nav
.Map<LoginViewModel, LoginPage>("login")
.Map<ChatHostViewModel, ChatHostPage>("chats"))
.UseDialogs()
.UseAuth<AuthLoginViewModel>());
services.AddSingleton<IAuthState>(sp =>
new SecureSessionAuthState(sp.GetRequiredService<ISecureSession>()));
services.RemoveAll<IPageNavigator>();
services.AddSingleton<IPageNavigator>(sp =>
new MauiPageNavigator(MauiWindowContext.Current, sp)
.Map<PageStackViewModel, PageStackPage>("stack"));Feature modules
IModule / AddModule<T>() is a thin composition boundary. A feature assembly registers its own routes, ViewModels, and services. It is not a Prism region catalog.
public sealed class CatalogModule : IModule
{
public void Configure(IServiceCollection services)
{
services.AddSingleton<ICatalog, Catalog>();
}
}
builder.Services.AddModule<CatalogModule>();