Schemat komunikacji w Messenger w oprogramowaniu Prism 9.0

Messenger w Prism 9.0

Messenger w Prism to bardzo ważny mechanizm do komunikacji wewnętrznej w aplikacjach, szczególnie w tych opartych na wzorcu MVVM (Model-View-ViewModel). W skrócie, jest to narzędzie umożliwiające wymianę wiadomości pomiędzy różnymi komponentami aplikacji w sposób luźno powiązany, co sprzyja lepszej organizacji kodu i unika bezpośrednich zależności między komponentami.

Messenger w Prism oparty jest na wzorcu Publish/Subscribe (Pub/Sub), co oznacza, że jedna część aplikacji (publisher) może wysyłać wiadomości, które będą odbierane przez inne części aplikacji (subscribers), które zarejestrowały się do tych wiadomości. W ten sposób można łatwo przekazywać informacje między różnymi częściami aplikacji, nie martwiąc się o bezpośrednią interakcję między nimi.

Jak działa Messenger w Prism?

W Prism Messenger oparty jest na klasie Messenger, która znajduje się w przestrzeni nazw Prism.Messaging. Dzięki temu mechanizmowi, różne elementy aplikacji mogą wysyłać wiadomości, które będą odbierane przez inne elementy aplikacji, bez konieczności bezpośredniej komunikacji pomiędzy nimi.

Kluczowe koncepcje:

  1. Publish: Komponent A (np. ViewModel) wysyła wiadomość.
  2. Subscribe: Komponent B (np. Inny ViewModel) subskrybuje te wiadomości i odbiera je.
  3. Luźne powiązanie: Komponenty nie muszą znać się nawzajem. Komponent A nie musi wiedzieć, który komponent odbiera jego wiadomość.

Wzorzec Publish/Subscribe

  • Publisher (Publisher Component): Komponent wysyła wiadomość. Może to być akcja użytkownika, np. kliknięcie przycisku, zmiana stanu w aplikacji, itp.
  • Subscriber (Subscriber Component): Komponent subskrybuje wiadomości, na które chce reagować. Można mieć wiele subskrybentów dla jednej wiadomości.

Przykład implementacji z użyciem Messenger:

using Prism.Mvvm;
using Prism.Commands;
using Prism.Messaging;
using System;

namespace PrismExample
{
    // 1. Definiowanie klasy wiadomości
    public class MyMessage
    {
        public string Content { get; set; }
    }

    public class MainWindowViewModel : BindableBase
    {
        private readonly IMessenger _messenger;

        public DelegateCommand SendMessageCommand { get; private set; }

        public MainWindowViewModel(IMessenger messenger)
        {
            _messenger = messenger;

            // 2. Rejestracja subskrybenta
            _messenger.Register<MyMessage>(this, (message) =>
            {
                // Reakcja na otrzymaną wiadomość
                Console.WriteLine("Otrzymano wiadomość: " + message.Content);
            });

            // 3. Tworzenie komendy
            SendMessageCommand = new DelegateCommand(SendMessage);
        }

        private void SendMessage()
        {
            // 4. Wysłanie wiadomości
            _messenger.Send(new MyMessage { Content = "Wiadomość z MainWindowViewModel!" });
        }
    }
}

Wyjaśnienie przykładu:

  1. Definiowanie wiadomości: Tworzymy klasę MyMessage, która będzie przechowywać dane wiadomości (w tym przypadku jest to prosty ciąg znaków). W praktyce wiadomość może zawierać bardziej złożone dane.
  2. Rejestracja subskrybenta: W MainWindowViewModel rejestrujemy subskrybenta, który nasłuchuje na wiadomości typu MyMessage. Za każdym razem, gdy taka wiadomość zostanie wysłana, zostanie wywołana funkcja obsługi (w tym przypadku po prostu wypisanie treści wiadomości na konsolę).
  3. Wysyłanie wiadomości: Używamy _messenger.Send, aby wysłać wiadomość. Każdy subskrybent, który zarejestrował się na ten typ wiadomości, zostanie powiadomiony o jej nadejściu.
  4. DelegateCommand: Komenda SendMessageCommand jest związana z akcją użytkownika (np. kliknięciem przycisku), która powoduje wysłanie wiadomości.

Korzyści z używania Messengera:

  1. Luźne powiązanie: Komponenty mogą się komunikować bez konieczności bezpośredniego odwoływania się do siebie. Komponent A (wysyłający wiadomość) nie musi znać szczegółów implementacji komponentu B (odbierającego wiadomość).
  2. Centralna komunikacja: Dzięki Messengerowi wszystkie wiadomości w aplikacji mogą być zarządzane w centralny sposób, co ułatwia kontrolowanie przepływu informacji.
  3. Skalowalność: Można łatwo dodać nowych subskrybentów, bez potrzeby zmiany innych części aplikacji.
  4. Bezpośrednia reakcja na zmiany: Dzięki subskrypcji na różne typy wiadomości, aplikacja może na bieżąco reagować na zmiany w modelu danych, interakcje z użytkownikiem lub inne zdarzenia systemowe.

Kiedy używać Messengera w Prism?

  • Wymiana danych między różnymi widokami: Jeśli chcesz, aby różne widoki lub ViewModel’e wymieniały się informacjami, ale nie chcesz tworzyć bezpośrednich zależności między nimi.
  • Powiadomienia systemowe: Jeśli chcesz mieć mechanizm powiadomień wewnątrz aplikacji, np. informowanie o zakończeniu jakiegoś procesu, błędzie, itp.
  • Przekazywanie informacji o zdarzeniach między komponentami: Gdy jeden komponent w aplikacji reaguje na zdarzenie, które wpływa na inne komponenty (np. kliknięcie przycisku zmienia stan innych kontrolek).

Przykład bardziej zaawansowanego użycia Messengera:

Załóżmy, że masz aplikację z różnymi ViewModel’ami, a jeden ViewModel chce wysłać powiadomienie o zakończeniu jakiegoś długotrwałego procesu do innych ViewModeli:

// Widok A - Proces z długotrwałym zadaniem
public class ProcessViewModel : BindableBase
{
    private readonly IMessenger _messenger;

    public DelegateCommand StartProcessCommand { get; private set; }

    public ProcessViewModel(IMessenger messenger)
    {
        _messenger = messenger;
        StartProcessCommand = new DelegateCommand(StartProcess);
    }

    private void StartProcess()
    {
        // Symulacja długotrwałego zadania
        Task.Run(() =>
        {
            Thread.Sleep(3000); // Symulacja pracy

            // Po zakończeniu procesu wysyłamy wiadomość
            _messenger.Send(new MyMessage { Content = "Proces zakończony!" });
        });
    }
}

// Widok B - Reakcja na zakończenie procesu
public class StatusViewModel : BindableBase
{
    private readonly IMessenger _messenger;

    public StatusViewModel(IMessenger messenger)
    {
        _messenger = messenger;

        // Subskrypcja na wiadomości
        _messenger.Register<MyMessage>(this, (message) =>
        {
            // Reakcja na zakończenie procesu
            Console.WriteLine("StatusViewModel otrzymał wiadomość: " + message.Content);
        });
    }
}

W tym przypadku, gdy proces się zakończy, ProcessViewModel wysyła wiadomość, a StatusViewModel reaguje na nią, np. wyświetlając komunikat na ekranie.

Podsumowanie:

Messenger w Prism to potężne narzędzie do komunikacji w aplikacjach. Dzięki wzorcowi Publish/Subscribe możesz tworzyć elastyczną, skalowalną komunikację między różnymi komponentami aplikacji, bez tworzenia twardych zależności. To kluczowe w aplikacjach opartych na MVVM, gdzie separacja odpowiedzialności i luźne powiązanie są ważne dla utrzymania czystości i organizacji kodu.

Podobne wpisy

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *