Communication entre les composants faiblement couplés
Conseil
Ce contenu est un extrait du livre électronique Modèles d’application d’entreprise avec .NET MAUI, disponible dans la .documentation .NET ou en tant que PDF téléchargeable gratuitement qui peut être lu hors connexion.
Le modèle publication-abonnement est un modèle de messagerie dans lequel les émetteurs envoient des messages sans avoir connaissance des destinataires, qui sont appelés abonnés. De même, les abonnés sont à l’écoute de messages spécifiques, sans avoir connaissance des émetteurs.
Les événements dans .NET implémentent le modèle publication-abonnement, et constituent l’approche la plus simple et la plus directe pour une couche de communication entre des composants si un couplage faible n’est pas nécessaire, comme un contrôle et la page qui le contient. Toutefois, les durées de vie de l’auteur et de l’abonné sont couplées l’une à l’autre par des références d’objet, et le type d’abonné doit avoir une référence au type d’auteur. Ceci peut créer des problèmes de gestion de la mémoire, en particulier quand il existe des objets à courte durée de vie qui s’abonnent à un événement d’un objet statique ou à longue durée de vie. Si le gestionnaire d’événements n’est pas supprimé, l’abonné est maintenu actif par la référence à celui-ci dans l’éditeur, ce qui empêche ou retarde le nettoyage de la mémoire de l’abonné.
Présentation de MVVM Toolkit Messenger
L’interface IMessenger
de MVVM Toolkit décrit le modèle publication-abonnement, permettant une communication basée sur les messages entre des composants qui sont peu pratiques à lier par références d’objet et de type. Ce mécanisme permet aux éditeurs et aux abonnés de communiquer sans qu’il y ait de référence directe l’un à l’autre, ce qui permet de réduire les dépendances entre les composants, tout en permettant aux composants d’être développés et testés indépendamment.
Notes
MVVM Toolkit Messenger fait partie du package CommunityToolkit.Mvvm
. Pour plus d’informations sur l’ajout du package à votre projet, consultez Présentation de MVVM Toolkit sur le Centre de développement Microsoft.
Avertissement
.NET MAUI intègre une classe MessagingCenter
dont l’utilisation n’est plus recommandée. Utilisez plutôt MVVM Toolkit Messenger.
L’interface IMessenger
autorise le fonctionnement de publication-abonnement en multidiffusion. Cela signifie que plusieurs émetteurs peuvent publier un même message et que plusieurs abonnés peuvent écouter le même message. L’image ci-dessous illustre cette relation :
Deux implémentations de l’interface IMessenger
sont fournies avec le package CommunityToolkit.Mvvm
. WeakReferenceMessenger
utilise des références faibles, ce qui peut faciliter le nettoyage pour les abonnés aux messages. C’est une bonne option si vos abonnés n’ont pas de cycle de vie clairement défini. StrongReferenceMessenger
utilise des références fortes qui peuvent se traduire par de meilleures performances et une durée de vie plus clairement contrôlée de l’abonnement. Si vous avez un workflow dont la durée de vie est très contrôlée (par exemple un abonnement lié aux méthodes OnAppearing
et OnDisappearing
d’une page), StrongReferenceManager
peut être une meilleure option si les performances sont importantes. Ces deux implémentations sont disponibles avec des implémentations par défaut prêtes à être utilisées en référençant WeakReferenceMessenger.Default
ou StrongReferenceMessenger.Default
.
Notes
Bien que l’interface IMessenger
autorise la communication entre des classes faiblement couplées, elle n’offre pas la seule solution en termes d’architecture à ce problème. Par exemple, la communication entre un modèle d’affichage et une vue peut également être obtenue par le moteur de liaison et par le biais de notifications de modification de propriété. En outre, la communication entre deux modèles de vue peut également être obtenue en transmettant des données pendant la navigation.
L’application multiplateforme eShop utilise la classe WeakReferenceMessenger
pour communiquer entre des composants faiblement couplés. L’application définit un seul message nommé AddProductMessage
. AddProductMessage
est publié par la classe CatalogViewModel
quand un élément est ajouté au panier d’achat. En retour, la classe CatalogView
s’abonne au message et l’utilise pour mettre en évidence les ajouts de produit avec une animation en réponse.
Dans l’application multiplateforme eShop, WeakReferenceMessenger
sert à mettre à jour l’interface utilisateur en réponse à une action qui se produit dans une autre classe. Ainsi, les messages sont publiés à partir du thread sur lequel la classe s’exécute, les abonnés recevant le message sur le même thread.
Conseil
Marshalez vers l’interface utilisateur ou le thread principal lors de l’exécution de mises à jour de l’interface utilisateur. Si aucune mise à jour des interfaces utilisateur n’est effectuée sur ce thread, l’application peut se bloquer ou devenir instable.
Si un message envoyé à partir d’un thread d’arrière-plan est nécessaire pour mettre à jour l’interface utilisateur, traitez le message sur le thread d’interface utilisateur dans l’abonné en appelant la méthode MainThread.BeginInvokeOnMainThread
.
Pour plus d’informations sur Messenger
, consultez Messenger dans le Centre de développement Microsoft.
Définition d’un message
Les messages IMessenger
sont des objets personnalisés qui fournissent des charges utiles personnalisées. L’exemple de code suivant montre le message AddProductMessage
défini dans l’application multiplateforme eShop :
public class AddProductMessage : ValueChangedMessage<int>
{
public AddProductMessage(int count) : base(count)
{
}
}
La classe de base est définie en utilisant ValueChangedMessage<T>
, où T
peut être de n’importe quel type nécessaire pour passer des données. Les émetteurs de messages et les abonnés peuvent s’attendre à des messages d’un type spécifique (par exemple AddProductMessage
). Ceci peut garantir que les deux parties ont convenu d’un contrat de messagerie et que les données fournies avec ce contrat seront cohérentes. En outre, cette approche fournit une sécurité des types à la compilation et la prise en charge de la refactorisation.
Publication d’un message
Pour publier un message, nous devons utiliser la méthode IMessenger.Send
. Ceci est accessible le plus souvent via WeakReferenceMessenger.Default.Send
ou StrongReferenceMessenger.Default.Send
. Le message envoyé peut être de n’importe quel type d’objet. L’exemple de code suivant illustre la publication du message AddProduct
:
WeakReferenceMessenger.Default.Send(new Messages.AddProductMessage(BadgeCount));
Dans cet exemple, la méthode Send
spécifiée fournit une nouvelle instance de l’objet AddProductMessage
que les abonnés en aval reçoivent. Un deuxième paramètre de jeton supplémentaire peut être ajouté pour être utilisé quand plusieurs abonnés différents doivent recevoir des messages du même type sans recevoir le message incorrect.
La méthode Send
va publier le message et toutes les données de sa charge utile en utilisant une approche « déclencher et oublier ». Le message est donc envoyé, même si aucun abonné n’est inscrit pour recevoir le message. Dans ce cas, le message envoyé est ignoré.
Abonnement à un message
Les abonnés peuvent s’abonner pour recevoir un message à l’aide de l’une des surcharges IMessenger.Register<T>
. L’exemple de code suivant montre comment l’application multiplateforme eShop s’abonne au message AddProductMessage
et le traite :
WeakReferenceMessenger.Default
.Register<CatalogView, Messages.AddProductMessage>(
this,
async (recipient, message) =>
{
await recipient.Dispatcher.DispatchAsync(
async () =>
{
await recipient.badge.ScaleTo(1.2);
await recipient.badge.ScaleTo(1.0);
});
});
Dans l’exemple précédent, la méthode Register
s’abonne au message AddProductMessage
et exécute un délégué de rappel en réponse à la réception du message. Ce délégué de rappel, spécifié en tant qu’expression lambda, exécute le code qui met à jour l’interface utilisateur.
Notes
Évitez l’utilisation de this
dans votre délégué de rappel pour éviter de capturer cet objet au sein du délégué. Ceci peut améliorer les performances. Au lieu de cela, utilisez le paramètre recipient
.
Si des données de charge utile sont fournies, n’essayez pas de modifier les données de charge utile à partir d’un délégué de rappel, car plusieurs threads peuvent accéder aux données reçues simultanément. Dans ce scénario, les données de charge utile doivent être immuables pour éviter les erreurs d’accès concurrentiel.
Se désabonner d’un message
Les abonnés peuvent se désinscrire des messages qu’ils ne souhaitent plus recevoir. Ceci est obtenu avec une des surcharges de IMessenger.Unregister
, comme illustré dans l’exemple de code suivant :
WeakReferenceMessenger.Default.Unregister<Messages.AddProductMessage>(this);
Notes
Dans cet exemple, il n’est pas entièrement nécessaire d’appeler Unregister
, car WeakReferenceMessenger
va permettre de nettoyer les objets inutilisés. Si StrongReferenceMessenger
était utilisé, il serait conseillé d’appeler Unregister
pour tous les abonnements qui ne sont plus en cours d’utilisation.
Dans cet exemple, la syntaxe de méthode Unsubscribe
spécifie l’argument de type du message et l’objet destinataire qui écoute les messages.
Résumé
L’interface IMessenger
de MVVM Toolkit décrit le modèle publication-abonnement, permettant une communication basée sur les messages entre des composants qui sont peu pratiques à lier par références d’objet et de type. Ce mécanisme permet aux éditeurs et aux abonnés de communiquer sans qu’il y ait de référence l’un à l’autre, ce qui permet de réduire les dépendances entre les composants, tout en permettant aux composants d’être développés et testés indépendamment.