Le problematiche più comuni di un'architettura M-V-VM con WPF

5 pagine in totale: <<Indietro 1 2 [3] 4 5 Avanti >>

Il mediator pattern

Nel paragrafo precedente si sono evidenziati l'utilità, ma anche i difetti di un approccio basato sugli eventi per far comunicare la View con il VM. La comunità degli sviluppatori non è nuova a queste problematiche, grazie anche all'esperienza fatta con altri framework e per questo scopo trova un'ottima applicazione il mediator pattern.

Dal punto di vista teorico esistono due attori: il mediator e il colleague. Il primo funge da oggetto coordinatore e intermediario tra più colleague i quali non si conoscono, ma comunicano grazie appunto al mediatore. Questo permette sia di disaccoppiare, mantenendo la possibilità di testare ogni singola unità, sia di non avere i limiti che si hanno con gli eventi, descritti in precedenza.

All'atto pratico nel MVVM Light Toolkit, citato ad iniziato articolo, è presente una classe Messenger che è il mediatore per lo scambio di messaggi tra la View e il VM. L'interfaccia di scambio di nome IMessageRecipient è adibita al semplice scambio di messaggi ed è così definita:

public interface IMessageRecipient 
{ 
    void ReceiveMessage(MessageBase message); 
}

Per realizzare come nel paragrafo precedente la chiusura dell'applicazione, si deve quindi implementare tale interfaccia per l'oggetto che vuole ricevere un messaggio, nel caso specifico la finestra. Quest'ultima per ricevere il messaggio deve inoltre registrarsi sulla classe Messenger e indicare quale tipo di messaggio vuole ricevere. Il tipo MessageBase è infatti generico e non porta alcuna informazione con se, perciò occorre definire un proprio messaggio o sfruttare quelli preconfezionati, come il CommandMessage che porta con sé una stringa identificativa del comando. Ecco quindi come la finestra si registra per ricevere il messaggio:

public partial class MainWindow : Window, IMessageRecipient 
{ 
    public MainWindow() 
    { 
        Messenger.Default.Register(this, typeof(CommandMessage)); 
    } 
}

La proprietà statica Default crea e restituisce in automatico un'istanza predefinita della classe Messenger, ma è possibile istanziarne una specifica per raggruppare un'insieme di messaggi e di ascoltatori a patto che questa istanza sia visibile da tutte le parti in causa.

L'implementazione dell'interfaccia si deve quindi limitare ad identificare il tipo di messaggio, valutarne le informazioni ed eseguire l'eventuale operazione. Nell'esempio preso in considerazione si verifica se il comando è quello di chiusura per agire poi di conseguenza.

void IMessageRecipient.ReceiveMessage(MessageBase message) 
{ 
    CommandMessage cm = message as CommandMessage; 
    if (cm != null && cm.Command == "Close") 
        this.Close(); 
}

L'implementazione della classe Messenger fa sì che il metodo ReceiveMessage venga invocato solo su quelle istanze che si sono registratate per quel tipo di messaggio, perciò questa tecnica gode di buone prestazioni. Inoltre il mediatore mantiene al suo interno una WeakReference dell'istanza e di conseguenza non è richiesto togliere la registrazione qualora l'istanza della finestra muoia. Il tutto viene automaticamente gestito dal CLR consentendo di dimenticarsi completamente del processo di messaggistica.

A questo punto non resta che mandare il messaggio dove richiesto, sull'implementazione del comando CloseApplicationCommand situato nel VM.

private void Close() 
{ 
    Messenger.Default.Broadcast(new CommandMessage(this, "Close")); 
}

Facendo riferimendo alla stessa istanza di Messenger, si trasmette il messaggio creato a chi è in ascolto: la View. Nel toolkit preso in considerazione esistono altri messaggi già pronti all'uso:

  • GenericMessage: dispone di una proprietà Content che fa da contenitore dove è possibile inserire qualsiasi oggetto di tipo T;
  • DialogMessage: identifica la richiesta di mostrare una finestra di dialogo, trasmettendo il titolo, il messaggio, i pulsanti e un eventuale callback da chiamare;
  • PropertyChangedMessage: messaggio per identificare il cambio di una proprietà.

Il tipo di messaggio è quindi la discrimintante per identificare l'operazione da eseguire e in generale il tipo di notifica. Può però essere esteso con una proprietà per avere informazioni aggiuntive, come nel caso del CommandMessage, e permette di supportare diversi scenari: finestre di dialogo, finestre modali, visualizzazione degli errori e notifiche di operazioni.

La tecnica illustrata è piuttosto rapida da utilizzare, garantisce il disaccoppiamento e permette facilmente di creare mock che permettano di intercettare il messaggio e di testare l'intero ciclo di trasmissione dei messaggi.

5 pagine in totale: <<Indietro 1 2 [3] 4 5 Avanti >>

Attenzione: Questo articolo contiene un allegato.

Contenuti dell'articolo

Commenti

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Segnala su:  Facebook  Messenger  Twitter        |

TUTORIALS

Silverlight

.NET Framework

Accesso ai dati

Architettura e design software

Windows Azure

TOP TEN ARTICOLI
ARTICOLI VIA E-EMAIL

Iscriviti alla nostra newsletter nuoviarticoli per ricevere via e-mail le notifiche!

Iscrivi subito! »»»

MEDIA
IN EVIDENZA
MISC