Modifier

Partager via


CommunityToolkit.Mvvm.Messaging Namespace

Classes

IMessengerExtensions

Extensions for the IMessenger type.

StrongReferenceMessenger

A class providing a reference implementation for the IMessenger interface.

WeakReferenceMessenger

A class providing a reference implementation for the IMessenger interface.

Interfaces

IMessenger

An interface for a type providing the ability to exchange messages between different objects. This can be useful to decouple different modules of an application without having to keep strong references to types being referenced. It is also possible to send messages to specific channels, uniquely identified by a token, and to have different messengers in different sections of an applications. In order to use the IMessenger functionalities, first define a message type, like so:

public sealed class LoginCompletedMessage { }

Then, register your a recipient for this message:

Messenger.Default.Register<MyRecipientType, LoginCompletedMessage>(this, (r, m) =>
{
    // Handle the message here...
});

The message handler here is a lambda expression taking two parameters: the recipient and the message. This is done to avoid the allocations for the closures that would've been generated if the expression had captured the current instance. The recipient type parameter is used so that the recipient can be directly accessed within the handler without the need to manually perform type casts. This allows the code to be less verbose and more reliable, as all the checks are done just at build time. If the handler is defined within the same type as the recipient, it is also possible to directly access private members. This allows the message handler to be a static method, which enables the C# compiler to perform a number of additional memory optimizations (such as caching the delegate, avoiding unnecessary memory allocations). Finally, send a message when needed, like so:

Messenger.Default.Send<LoginCompletedMessage>();

Additionally, the method group syntax can also be used to specify the message handler to invoke when receiving a message, if a method with the right signature is available in the current scope. This is helpful to keep the registration and handling logic separate. Following up from the previous example, consider a class having this method:

private static void Receive(MyRecipientType recipient, LoginCompletedMessage message)
{
    // Handle the message there
}

The registration can then be performed in a single line like so:

Messenger.Default.Register(this, Receive);

The C# compiler will automatically convert that expression to a MessageHandler<TRecipient,TMessage> instance compatible with Register<TRecipient,TMessage>(IMessenger, TRecipient, MessageHandler<TRecipient,TMessage>). This will also work if multiple overloads of that method are available, each handling a different message type: the C# compiler will automatically pick the right one for the current message type. It is also possible to register message handlers explicitly using the IRecipient<TMessage> interface. To do so, the recipient just needs to implement the interface and then call the RegisterAll(IMessenger, Object) extension, which will automatically register all the handlers that are declared by the recipient type. Registration for individual handlers is supported as well.

IRecipient<TMessage>

An interface for a recipient that declares a registration for a specific message type.

Delegates

MessageHandler<TRecipient,TMessage>

A delegate used to represent actions to invoke when a message is received. The recipient is given as an input argument to allow message registrations to avoid creating closures: if an instance method on a recipient needs to be invoked it is possible to just cast the recipient to the right type and then access the local method from that instance.