piątek, 29 października 2010

Prosty wrapper Messengera z MVVM Light Toolkit

Od razu zaznaczam, że pomysł nie jest mój, ale jest zaczerpnięty z przykładowego projektu na CodeProject. Jednak spodobał mi się bardzo, bo wprowadza porządek do projektu, jest prosty i oczywisty. 

W czym problem?
Podczas korzystania z Messengera, problemem okazało się tworzenie unikalnych tokenów za pomocą, których można by jednoznacznie identyfikować komunikaty. Dzięki tokenom można przesyłać wiele komunikatów tego samego typu (na przykład w prostym przypadku string'ów) i jednocześnie móc je od siebie odróżnić. Pozwala to także uniknąć konieczności tworzenia własnych klas komunikatów nawet dla prostych przypadków. 
Używanie ciągów znakowych wpisywanych z palca jako tokenów (na przykład "SelectedDirectoryChanged") jest niewygodne, podatne na literówki i nie daje żadnego wsparcia dla IntelliSense'a. Chciałem rozwiązać ten problem przez przechowywanie takich tekstowych tokenów w zasobach, ale okazało się to niewygodne i kłopotliwe. 

Rozwiązanie
Aby poradzić sobie z tym problem i jeszcze dodatkowo za darmo otrzymać wygodniejszy sposób posługiwania się komunikatami należy stworzyć statyczną klasę (AppMessages), która będzie wrapperem na Messengera. Najpierw deklarujemy enum'a, który będzie przechowywał wszystkie typy komunikatów jakie będziemy przesyłać:
enum MessageTypes
{
 SelectedDirectoryChanged,
 PhotoSourceChanged,
 AddPhoto, 
 SavePhoto
}
Następnie dla każdego komunikatu należy stworzyć osobną statyczną klasę wewnątrz AppMessages, która będzie posiadać dwie funkcje Send oraz Register. Ich jedynym zadaniem jest wywołanie odpowiednich funkcji Messengera, np:
public static class SelectedDirectoryMessage
{
 public static void Send(Models.DirectoryItem item)
 {
  Messenger.Default.Send<models.directoryitem>(item, MessageTypes.SelectedDirectoryChanged);
 }

 public static void Register(object recipient, Action<models.directoryitem> action)
 {
  Messenger.Default.Register<models.directoryitem>(recipient, MessageTypes.SelectedDirectoryChanged, action);
 }
}
Dzięki takiemu podejściu zyskujemy bardzo prosty i czytelny sposób obsługi komunikatów:
//rejestrowanie akcji reagującej na komunikat
AppMessages.SelectedDirectoryMessage.Register(this,
 item =>
 {
  this.CurrentDirectory = item.Path;
 });
 
//wysyłanie komunikatu
AppMessages.SelectedDirectoryMessage.Send(_fileitem);
Unikamy wpisywania za każdym razem tasiemców, w których trzeba podawać typy przesyłanych danych, robimy to tylko raz pisząc klasę obsługi komunikatu. 

Snippet do generowania klas obsługi komunikatów
Tworzenie nowych klas dla nowych komunikatów jest wtórne i powtarzalne, dlatego zrobiłem sobie snippet który generuje nową klasę i pozwala wpisać wszystkie parametry. Nie ma w nim nic nadzwyczajnego, ale pomimo tego jakby ktoś chciał go użyć wrzuciłem go tutaj.

Brak komentarzy:

Prześlij komentarz