In effetti, entrambe queste soluzioni sono pessime.
Creating a services singleton (IServices) containing all the available services as interfaces. Example: Services.Current.XXXService.Retrieve(), Services.Current.YYYService.Retrieve(). That way, I don't have a huge constructor with a ton of services parameters in them.
Questo è essenzialmente il Pattern Locator del servizio , che è un anti-pattern. Se lo fai, non sarai più in grado di capire di cosa sia effettivamente il modello di visualizzazione, senza considerare la sua implementazione privata, il che renderà molto difficile il test o il refactoring.
Creating a facade for the services used by the viewModel and passing this object in the ctor of my viewmodel. But then, I'll have to create a facade for each of my complexe viewmodels, and it might be a bit much...
Questo non è tanto un anti-pattern ma è un odore di codice. Essenzialmente stai creando un oggetto parametro , ma il punto del pattern di refactoring PO è quello di gestire i set di parametri che sono usati frequentemente e in molti posti diversi , mentre questo parametro dovrebbe essere usato solo una volta. Come hai detto, creerebbe un sacco di codice gonfiato senza alcun beneficio reale e non sarebbe stato piacevole con molti contenitori IoC.
In effetti, entrambe le strategie di cui sopra stanno trascurando il problema generale, ovvero che l'accoppiamento è troppo alto tra i modelli di visualizzazione e i servizi . Semplicemente nascondere queste dipendenze in un localizzatore di servizi o in un oggetto parametro in realtà non modifica di quanti altri oggetti dipende dal modello di visualizzazione.
Pensa a come testare unitamente uno di questi modelli di visualizzazione. Quanto sarà grande il tuo codice di installazione? Quante cose devono essere inizializzate affinché funzioni?
Molte persone che iniziano con MVVM cercano di creare modelli di visualizzazione per uno intero schermo , che è fondamentalmente l'approccio sbagliato. MVVM riguarda la composizione e una schermata con molte funzioni dovrebbe essere composta da diversi modelli di visualizzazione, ognuno dei quali dipende da uno o pochi modelli / servizi interni. Se hanno bisogno di comunicare tra loro, lo fai tramite pub / sub (broker di messaggi, bus eventi, ecc.)
Ciò che in realtà è necessario è il refactoring dei tuoi modelli di vista in modo che abbiano meno dipendenze . Quindi, se è necessario disporre di uno "schermo" aggregato, si crea un altro modello di vista per aggregare i modelli di vista più piccoli. Questo modello di vista aggregato non deve fare molto da solo, quindi a sua volta è anche abbastanza facile da capire e testare.
Se l'hai fatto correttamente, dovrebbe essere ovvio solo guardando il codice, perché avrai modelli di visualizzazione brevi, concisi, specifici e testabili.