Strange exception in Prism application

2019-05-05 17:11发布

问题:

I am trying to get a Prism application to start up, and am getting a very strange error:

InvalidOperationException: ServiceLocationProvider must be set.

I am using MainWindow in the main (module host) application as the region for a single main shell, that has it's own regions. That way I can swap out main window layouts if needed.

I get the error on the InitializeComponent(); call, the only line of code in the constructor of MainWindow. Google and Bing both return zero results for that exact phrase.

The XAML element in MainWindow is:

<ContentControl regions:RegionManager.RegionName="MainShellRegion" />

Do I have to implement some interface or something on MainWindow to solve this? I am completely stumped.

回答1:

You need to set up dependency injection for your Prism application, otherwise it won't be able to run. This should be done from inside your bootstrapper, inside the ConfigureServiceLocator method.

To expand a bit on the above, Prism is wired so that whenever it needs access to an application component it does not initialize the component directly (how would it know which implementation to use and how to initialize it?) but rather it delegates this job to a service locator.

The service locator is a component whose responsibility is to fulfill requests for one component made by another, allowing the two components to be decoupled. It is your responsibility as the developer to instantiate and configure the service locator and make it available to Prism; this is done during application startup (hence inside the bootstrapper).



回答2:

As Jon wrote, Prism needs the ServiceLocator to be set. This is done in the bootstrapper and should happen in the abstract ConfigureServiceLocator method. The MefBootstrapper or UnityBootstrapper have an implementation for that method where the service locator is set based on the composition container (which itself is set in ConfigureContainer).

These methods (and many more) are all called as part of the Run method on the bootstrapper.

So my guess is that you are not calling the bootstrapper correctly. You code should look something like this:

public class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        var bootstrapper = new MyBootstrapper();
        bootstrapper.Run();
    }
}

Everything else should be done in the appropriate methods on the bootstrapper.