Search code examples
wpfprism

Wpf Prism shell view model resolved before module


I'm new to using Prism (using v8) with a WPF app. I have created a module assembly and registered it with the app:

protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
    base.ConfigureModuleCatalog(moduleCatalog);
    moduleCatalog.AddModule<ApplicationModule>();
}

The module registers a singleton instance of MyApplication.

public class ApplicationModule : IModule
{
    public void RegisterTypes(IContainerRegistry containerRegistry)
    {
        containerRegistry.RegisterSingleton<IMyApplication, MyApplication>();
    }

    public void OnInitialized(IContainerProvider containerProvider)
    {
    }
}

The ShellView is auto-wired to the ShellViewModel.

public class ShellViewModel : BindableBase
{
    private readonly IDialogService? _dialogService;

    public ShellViewModel(IDialogService dialogService)
    {
        NewCommand = new DelegateCommand(NewExecute);

        _dialogService = dialogService;
    }

    public DelegateCommand NewCommand { get; private set; }

    private void NewExecute()
    {
        _dialogService?.Present("sample message", "sample caption");
    }
}

Now this all works as is, but if I put a reference to IMyApplication into the ShellViewModel constructor so that I can have a reference to it, the whole thing crashes because it doesn't exist yet and it can't be injected.

So I put in a breakpoint on the AddModule call and the ShellViewModel constructor, and that constructor is being called before RegisterSingleton is called, so I'm guessing I've done something incorrectly.

Where have I gone wrong?


Solution

  • Where have I gone wrong?

    You're doing it right. You've discovered a limitation of the module-system in Prism: the shell's view model must not depend on anything registered in modules.

    While this seems annoying at first, it enables you to show the shell while loading the modules in the background. And you can, most of the time, work around it by injecting Lazy<IServiceFromModule> into ShellViewModel instead of IServiceFromModule - it will not be resolved until you actually use it. As long as you use it after the modules are initialized, you're fine.