Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the correct INavigationService instance on resolving a type manually in Prism application

It seems that when I resolve a type manually and request the INavigationService in it a different instance is injected than the one being used everywhere else.

To clearify my use-case here are excerpts from the relevant files. As you can see when resolving the type SampleProcess the INavigationService will be injected but the instance is different to the one that I got in ProcessService. (Which btw is the correct instance, that can be used for navigation. The one injected in SampleProcess cannot be used for navigating.)

Any ideas why this is happening and more importantely how I can get the correct instance of INavigationService be injected into SampleProcess. Yes, I could provide it for example by passing it in with a method, but that's not so pretty.

App.xaml.cs

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
    containerRegistry.RegisterSingleton<ProcessService>();
    containerRegistry.Register<Processes.SampleProcess>();
}

ProcessService.cs

public class ProcessService
{
    private readonly IContainer container;
    private readonly INavigationService navigationService;

    public ProcessService(IContainer container, INavigationService navigationService)
    {
        this.container = container;
        this.navigationService = navigationService;
    }

    public void ExecuteProcess(ProcessEnum processEnumValue)
    {
        Type processType = processEnumValue switch
        {
            ProcessEnum.SampleProcess => typeof(Processes.SampleProcess),
            _ => throw new NotImplementedException()
        };

        var process = App.Current.Container.Resolve(processType) as IProcess;

        bool test = process.CheckNavigationService(navigationService); // will return false
    }
}

SampleProcess.cs

public class SampleProcess : IProcess
{
    private readonly INavigationService navigationService;

    public SampleProcess(INavigationService navigationService)
    {
        this.navigationService = navigationService;
    }

    public bool CheckNavigationService(INavigationService navigationService)
    {
        return this.navigationService == navigationService;
    }
}
like image 998
Christoph Mett Avatar asked Nov 06 '22 05:11

Christoph Mett


1 Answers

Navigation in Prism is based on which page you are Navigating from. For this reason the NavigationService is a transient service. It is constructed special for your ViewModel so that the instance provided for you is aware of which page it will need to Navigate from.

There are several potential solutions for your issue.

  1. Don't inject the INavigationService into another service as it isn't meant to be handled that way.

  2. Provide the INavigationService as a parameter that you pass to whatever service needs to use it

  3. Simply make your ProcessService a transient

  4. Update to Prism 8 and make your Process Service a Scoped Service as we've made a change in Prism 8 that creates a new scope each time a new page is created. This means that any Scoped or Transient services that need access to the NavigationService would be able to inject the same exact instance that is injected into the ViewModel

like image 61
Dan Siegel Avatar answered Nov 12 '22 15:11

Dan Siegel