web-dev-qa-db-fra.com

ServiceLocationProvider doit être défini

J'utilise MVVM Light. Lorsque j'ajoute plus de convertisseurs de valeur dans mes ressources, mon application se bloque avec une exception:

Une exception de type 'System.InvalidOperationException' s'est produite dans Microsoft.Practices.ServiceLocation.DLL mais n'a pas été gérée dans le code utilisateur.

Informations complémentaires: ServiceLocationProvider doit être défini.

Dans l'événement App.xaml.cs OnLaunched, j'ai cette ligne

ServiceLocator.Current.GetInstance<MyViewModel>();

Il se bloque là-bas. Dans ce ServiceLocator, je peux voir qu'il existe une méthode SetLocatorProvider qui prend comme argument ServiceLocatorProvider. Je n'ai rien trouvé dans le Web et la page MSDN de Microsofts est datée:

protected override async void OnLaunched(LaunchActivatedEventArgs e)
    {
        Frame rootFrame = Window.Current.Content as Frame;

        if (rootFrame == null)
        {
            ...
        }

        if (rootFrame.Content == null)
        {
            ...
        }

        Window.Current.Activate();

        DispatcherHelper.Initialize();

        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        ServiceLocator.Current.GetInstance<MyViewModel>();
    }

EDIT: Voici l’événement complet OnLaunched. Après avoir mis 

ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

une exception se produit:

Une exception de type Microsoft.Practices.ServiceLocation.ActivationException 's'est produite dans GalaSoft.MvvmLight.Extras.DLL mais n'a pas été gérée dans le code utilisateur.

Informations complémentaires: Type introuvable dans le cache: cMC.ViewModel.MyViewModel.

C'est le code de ViewModelLocator

public class ViewModelLocator
{
    public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        SimpleIoc.Default.Register<MyViewModel>();
    }

    public MyViewModel MyVM
    {
        get
        {
            return ServiceLocator.Current.GetInstance<MyViewModel>();
        }
    }

    public static void Cleanup() {}
}
8
v.g.

Je l'ai un peu compris.

Il était également nécessaire d’enregistrer le ViewModel, ce qui s’est passé dans le constructeur ViewModelLocator, mais pour une raison quelconque, le constructeur est exécuté ultérieurement. J'ai donc modifié la classe ViewModelLocator comme ceci:

public class ViewModelLocator
{
    public ViewModelLocator()
    {

    }

    public static void SetAndReg()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        SimpleIoc.Default.Register<MyViewModel>();
    }

    public MyViewModel MyVM
    {
        get
        {
            return ServiceLocator.Current.GetInstance<MyViewModel>();
        }
    }

    public static void Cleanup() {}
}

}

Puis dans le fichier App.xaml.cs:

...OnLaunched(...)
{
...
        DispatcherHelper.Initialize();

        ViewModelLocator.SetAndReg();

        ServiceLocator.Current.GetInstance<MyViewModel>();
...
}
5
v.g.

Vous ne définissez pas le LocationProvider (le message d'erreur est assez évident ..):

Vous devez donner à ServiceLocator le conteneur IoC de votre choix: Voir cet exemple qui utilise Unity et un adaptateur:

static ViewModelLocator()
    {
        var container = new UnityContainer();
        ServiceLocator.SetLocatorProvider(() => new UnityServiceLocatorAdapter(container));

        container.RegisterInstance<ILoggingService>(new ConsoleLoggingService());
        container.RegisterInstance<IMessageBoxService>(new SimpleMessageBoxService());
        container.RegisterInstance<ITestSuiteService>(new TestSuiteService());
        container.RegisterInstance<IApplicationService>(new ApplicationService());
    }

    /// <summary>
    /// Gets the <see cref="BackstageAboutViewModel"/>.
    /// </summary>
    public BackstageAboutViewModel BackstageAboutViewModel
    {
        get
        {
            return ServiceLocator.Current.GetInstance<BackstageAboutViewModel>();
        }
    }
1
Xeun