Delen via


Communiceren tussen losjes gekoppelde onderdelen

Tip

Deze inhoud is een fragment uit het eBook, Enterprise Application Patterns Using .NET MAUI, beschikbaar op .NET Docs of als een gratis downloadbare PDF die offline kan worden gelezen.

Enterprise Application Patterns Using .NET MAUI eBook cover thumbnail.

Het patroon publish-subscribe is een berichtenpatroon waarin uitgevers berichten verzenden zonder dat ze ontvangers kennen, ook wel abonnees genoemd. Op dezelfde manier luisteren abonnees naar specifieke berichten, zonder dat ze uitgevers kennen.

Gebeurtenissen in .NET implementeren het patroon publish-subscribe en zijn de eenvoudigste methode voor een communicatielaag tussen onderdelen als losse koppeling niet vereist is, zoals een besturingselement en de pagina die het bevat. De levensduur van de uitgever en abonnee wordt echter gekoppeld door objectverwijzingen naar elkaar en het abonneetype moet een verwijzing naar het uitgeverstype hebben. Dit kan problemen met geheugenbeheer creëren, met name wanneer er kortdurende objecten zijn die zich abonneren op een gebeurtenis van een statisch of langlopend object. Als de gebeurtenis-handler niet wordt verwijderd, wordt de abonnee actief gehouden door de verwijzing ernaar in de uitgever. Hierdoor wordt de garbagecollection van de abonnee voorkomen of vertraagd.

Inleiding tot MVVM Toolkit Messenger

De interface van de MVVM Toolkit IMessenger beschrijft het patroon publish-subscribe, waardoor communicatie op basis van berichten tussen onderdelen die onhandig zijn om te koppelen op object- en typeverwijzingen. Dit mechanisme stelt uitgevers en abonnees in staat om te communiceren zonder een directe verwijzing naar elkaar te hebben, waardoor afhankelijkheden tussen onderdelen kunnen worden verminderd, terwijl ook onderdelen onafhankelijk kunnen worden ontwikkeld en getest.

Notitie

De MVVM Toolkit Messenger maakt deel uit van het CommunityToolkit.Mvvm pakket. Zie Inleiding tot de MVVM Toolkit in het Microsoft Developer Center voor meer informatie over het toevoegen van het pakket aan uw project.

Waarschuwing

.NET MAUI bevat een ingebouwde MessagingCenter klasse die niet meer wordt aanbevolen voor gebruik. Gebruik in plaats daarvan de MVVM Toolkit Messenger.

De IMessenger interface biedt functionaliteit voor het publiceren en abonneren op multicast. Dit betekent dat er meerdere uitgevers kunnen zijn die één bericht publiceren en dat er meerdere abonnees naar hetzelfde bericht luisteren. In de onderstaande afbeelding ziet u deze relatie:

Multicast publish-subscribe-functionaliteit.

Er zijn twee implementaties van de IMessenger interface die bij het CommunityToolkit.Mvvm pakket worden geleverd. Het WeakReferenceMessenger maakt gebruik van zwakke verwijzingen die ertoe kunnen leiden dat berichtenabonnees gemakkelijker kunnen worden opgeschoond. Dit is een goede optie als uw abonnees geen duidelijk gedefinieerde levenscyclus hebben. Het StrongReferenceMessenger maakt gebruik van sterke verwijzingen die kunnen leiden tot betere prestaties en een duidelijker beheerde levensduur van het abonnement. Als u een werkstroom hebt met een zeer gecontroleerde levensduur (bijvoorbeeld een abonnement dat is gebonden aan de en OnDisappearing methoden van OnAppearing een pagina), is het mogelijk een betere optie als de StrongReferenceManager prestaties een probleem zijn. Beide implementaties zijn beschikbaar met standaard implementaties die gereed zijn voor gebruik door te verwijzen naar of WeakReferenceMessenger.Default StrongReferenceMessenger.Default.

Notitie

Hoewel de interface communicatie tussen losjes gekoppelde klassen toestaat, biedt deze IMessenger niet de enige architectuuroplossing voor dit probleem. Communicatie tussen een weergavemodel en een weergave kan bijvoorbeeld ook worden bereikt door de bindingsengine en via meldingen over eigenschappenwijziging. Daarnaast kan communicatie tussen twee weergavemodellen ook worden bereikt door gegevens door te geven tijdens de navigatie.

De eShop-app voor meerdere platforms maakt gebruik van de WeakReferenceMessenger klasse om te communiceren tussen losjes gekoppelde onderdelen. De app definieert één bericht met de naam AddProductMessage. Het AddProductMessage wordt door de CatalogViewModel klas gepubliceerd wanneer een item wordt toegevoegd aan het winkelwagentje. Als resultaat abonneert de CatalogView klasse zich op het bericht en gebruikt deze om het product te markeren dat wordt toegevoegd met animatie als antwoord.

In de eShop-app WeakReferenceMessenger voor meerdere platforms wordt de gebruikersinterface bijgewerkt als reactie op een actie die in een andere klasse plaatsvindt. Berichten worden daarom gepubliceerd vanuit de thread waarop de klasse wordt uitgevoerd, waarbij abonnees het bericht op dezelfde thread ontvangen.

Tip

Marshal naar de gebruikersinterface of hoofdthread bij het uitvoeren van UI-updates. Als er geen updates voor gebruikersinterfaces worden uitgevoerd op deze thread, kan dit ertoe leiden dat de toepassing vastloopt of instabiel wordt.

Als een bericht dat wordt verzonden vanaf een achtergrondthread nodig is om de gebruikersinterface bij te werken, verwerkt u het bericht op de UI-thread in de abonnee door de MainThread.BeginInvokeOnMainThread methode aan te roepen.

Zie Messenger in het Microsoft Developer Center voor meer informatie.Messenger

Een bericht definiëren

IMessenger berichten zijn aangepaste objecten die aangepaste nettoladingen bieden. In het volgende codevoorbeeld ziet u het AddProductMessage bericht dat is gedefinieerd in de eShop-app met meerdere platforms:

public class AddProductMessage : ValueChangedMessage<int>
{
    public AddProductMessage(int count) : base(count)
    {
    }
}

De basisklasse wordt gedefinieerd met behulp ValueChangedMessage<T> van waar T elk type kan zijn dat nodig is om gegevens door te geven. Zowel berichtuitgevers als abonnees kunnen berichten van een specifiek type verwachten (bijvoorbeeld AddProductMessage). Dit kan ervoor zorgen dat beide partijen akkoord zijn gegaan met een berichtencontract en dat de gegevens die bij dat contract worden geleverd, consistent zijn. Daarnaast biedt deze aanpak compilatie-type veiligheid en herstructureringsondersteuning.

Een bericht publiceren

Als u een bericht wilt publiceren, moet u de IMessenger.Send methode gebruiken. Dit kan het meest worden geopend via WeakReferenceMessenger.Default.Send of StrongReferenceMessenger.Default.Send. Het verzonden bericht kan van elk objecttype zijn. In het volgende codevoorbeeld ziet u hoe u het AddProduct bericht publiceert:

WeakReferenceMessenger.Default.Send(new Messages.AddProductMessage(BadgeCount));

In dit voorbeeld geeft de Send methode een nieuw exemplaar van het AddProductMessage object op dat downstreamabonnees moeten ontvangen. Een extra tweede tokenparameter kan worden toegevoegd om te gebruiken wanneer meerdere verschillende abonnees berichten van hetzelfde type moeten ontvangen zonder het verkeerde bericht te ontvangen.

Met Send de methode worden het bericht en de nettoladinggegevens gepubliceerd met behulp van een fire-and-forget-benadering. Daarom wordt het bericht verzonden, zelfs als er geen abonnees zijn geregistreerd om het bericht te ontvangen. In dit geval wordt het verzonden bericht genegeerd.

Abonneren op een bericht

Abonnees kunnen zich registreren om een bericht te ontvangen met behulp van een van de IMessenger.Register<T> overbelastingen. In het volgende codevoorbeeld ziet u hoe de eShop-app met meerdere platforms zich abonneert op en verwerkt, het AddProductMessage bericht:

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);
                });
        });

In het voorgaande voorbeeld wordt de Register methode geabonneerd op het AddProductMessage bericht en wordt een callback-gemachtigde uitgevoerd als reactie op het ontvangen van het bericht. Deze callback-gemachtigde, die is opgegeven als een lambda-expressie, voert code uit waarmee de gebruikersinterface wordt bijgewerkt.

Notitie

Vermijd het gebruik van this binnen uw callback-gemachtigde om te voorkomen dat dat object binnen de gemachtigde wordt vastgelegd. Dit kan helpen de prestaties te verbeteren. Gebruik in plaats daarvan de parameter recipient.

Als nettoladinggegevens worden opgegeven, probeert u de nettoladinggegevens niet te wijzigen vanuit een callback-gemachtigde, omdat verschillende threads tegelijkertijd toegang hebben tot de ontvangen gegevens. In dit scenario moeten de nettoladinggegevens onveranderbaar zijn om gelijktijdigheidsfouten te voorkomen.

Afmelden bij een bericht

Abonnees kunnen zich afmelden voor berichten die ze niet meer willen ontvangen. Dit wordt bereikt met een van de IMessenger.Unregister overbelastingen, zoals wordt weergegeven in het volgende codevoorbeeld:

WeakReferenceMessenger.Default.Unregister<Messages.AddProductMessage>(this);

Notitie

In dit voorbeeld is het niet volledig nodig om aan te roepen Unregister omdat WeakReferenceMessenger ongebruikte objecten worden verzameld. Als het StrongReferenceMessenger wordt gebruikt, wordt u aangeraden om te bellen Unregister voor abonnementen die niet meer in gebruik zijn.

In dit voorbeeld geeft de syntaxis van de Unsubscribe methode het typeargument van het bericht en het geadresseerdeobject op dat naar berichten luistert.

Samenvatting

De interface van de MVVM Toolkit IMessenger beschrijft het patroon publish-subscribe, waardoor communicatie op basis van berichten tussen onderdelen die onhandig zijn om te koppelen op object- en typeverwijzingen. Dit mechanisme stelt uitgevers en abonnees in staat om te communiceren zonder een verwijzing naar elkaar te hebben, waardoor afhankelijkheden tussen onderdelen kunnen worden verminderd, terwijl ook onderdelen onafhankelijk kunnen worden ontwikkeld en getest.