Trying to migrate from good old MVVM Light to Windows Community Toolkit. How are we supposed to override a registered service, i.e. replace it with another implementation at runtime?
I have got a UI layer which is basically a WPF application and a VM layer which is a class library. The structure looks like this:
App (UI)
MainWindow (window)
WPFDialogService (implements IDialog interface)
Library (VM)
IDialog (interface)
ConsoleDialogService (implements IDialog interface)
MainVM (backend of MainWindow)
ViewModelLocator (static class the performs Ioc registrations)
ViewModelLocator
is central hub and is supposed to register all services. By default, it registers ConsoleDialogService
as the default dialog service.
static ViewModelLocator()
{
services.AddSingleton<IDialogService>(new ConsoleDialogService())
.AddSingleton<MainVM>();
Ioc.Default.ConfigureServices(services.BuildServiceProvider());
}
But the UI layer is supposed to unregister that and inject a different service WPFDialogService
later (in the constructor of MainWindow
or in App
class).
In MVVM Light, we had Register
and Unregister
methods using which we could achieve this easily. However in WCT I do not see any equivalent. Am I supposed to call ConfigureServices()
again? How will it affect other services that are already registered? Is ther a way to replace a single service registration only without affecting others?
Also how do we manage service injection through constructors in WCT?
OK. I think I have finally found my way. Not sure if this is the standard/recommended approach, but it does solve the problem in an elegant way.
Problem with the standard MVVM Light approach is that the ViewModelLocator
class lives at the VM level, which by definition of MVVM, does not have access to View or Application layers. Therefore the implementations that live at those levels cannot be registered in ViewModelLocator
. As a remedy, MVVM Light provides register
and unregister
facility that we can call in those higher layers to replace existing registrations or introduce new ones.
When migrating/upgrading to Windows Community Toolkit, the whole idea of having a centralized ViewModel Locator must be avoided. Service registration must be performed at the highest level (e.g. Application layer) that has access to all implementations so as to select correct implementation (based on whatever criteria drive that selection). This will avoid the need of replacing/injecting any new registrations at a later stage.
Service injection should be entirely delegated to the service container. Introduce your service dependencies as constructor parameters and let your service container inject them automatically for you. No need of a centralized ViewModel Locator.
This approach can be used not only for the VM layer, but even for your UI components (windows/dialogs/custom control classes etc.). Just register them in your service container, add required dependences to their constructor and then whenever you need to instantiate an object, just call service container's GetService<T>
to let it do all the injection magic for you.