Skip to content

Commit af91276

Browse files
committed
Tweaked IMessenger and Messenger XML docs
1 parent d86f794 commit af91276

File tree

2 files changed

+53
-43
lines changed

2 files changed

+53
-43
lines changed

Microsoft.Toolkit.Mvvm/Messaging/IMessenger.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,54 @@ public delegate void MessageHandler<in TRecipient, in TMessage>(TRecipient recip
2323

2424
/// <summary>
2525
/// An interface for a type providing the ability to exchange messages between different objects.
26+
/// This can be useful to decouple different modules of an application without having to keep strong
27+
/// references to types being referenced. It is also possible to send messages to specific channels, uniquely
28+
/// identified by a token, and to have different messengers in different sections of an applications.
29+
/// In order to use the <see cref="IMessenger"/> functionalities, first define a message type, like so:
30+
/// <code>
31+
/// public sealed class LoginCompletedMessage { }
32+
/// </code>
33+
/// Then, register your a recipient for this message:
34+
/// <code>
35+
/// Messenger.Default.Register&lt;MyRecipientType, LoginCompletedMessage&gt;(this, (r, m) =>
36+
/// {
37+
/// // Handle the message here...
38+
/// });
39+
/// </code>
40+
/// The message handler here is a lambda expression taking two parameters: the recipient and the message.
41+
/// This is done to avoid the allocations for the closures that would've been generated if the expression
42+
/// had captured the current instance. The recipient type parameter is used so that the recipient can be
43+
/// directly accessed within the handler without the need to manually perform type casts. This allows the
44+
/// code to be less verbose and more reliable, as all the checks are done just at build time. If the handler
45+
/// is defined within the same type as the recipient, it is also possible to directly access private members.
46+
/// This allows the message handler to be a static method, which enables the C# compiler to perform a number
47+
/// of additional memory optimizations (such as caching the delegate, avoiding unnecessary memory allocations).
48+
/// Finally, send a message when needed, like so:
49+
/// <code>
50+
/// Messenger.Default.Send&lt;LoginCompletedMessage&gt;();
51+
/// </code>
52+
/// Additionally, the method group syntax can also be used to specify the message handler
53+
/// to invoke when receiving a message, if a method with the right signature is available
54+
/// in the current scope. This is helpful to keep the registration and handling logic separate.
55+
/// Following up from the previous example, consider a class having this method:
56+
/// <code>
57+
/// private static void Receive(MyRecipientType recipient, LoginCompletedMessage message)
58+
/// {
59+
/// // Handle the message there
60+
/// }
61+
/// </code>
62+
/// The registration can then be performed in a single line like so:
63+
/// <code>
64+
/// Messenger.Default.Register(this, Receive);
65+
/// </code>
66+
/// The C# compiler will automatically convert that expression to a <see cref="MessageHandler{TRecipient,TMessage}"/> instance
67+
/// compatible with <see cref="MessengerExtensions.Register{TRecipient,TMessage}(IMessenger,TRecipient,MessageHandler{TRecipient,TMessage})"/>.
68+
/// This will also work if multiple overloads of that method are available, each handling a different
69+
/// message type: the C# compiler will automatically pick the right one for the current message type.
70+
/// It is also possible to register message handlers explicitly using the <see cref="IRecipient{TMessage}"/> interface.
71+
/// To do so, the recipient just needs to implement the interface and then call the
72+
/// <see cref="MessengerExtensions.RegisterAll(IMessenger,object)"/> extension, which will automatically register
73+
/// all the handlers that are declared by the recipient type. Registration for individual handlers is supported as well.
2674
/// </summary>
2775
public interface IMessenger
2876
{

Microsoft.Toolkit.Mvvm/Messaging/Messenger.cs

Lines changed: 5 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,50 +12,12 @@
1212
namespace Microsoft.Toolkit.Mvvm.Messaging
1313
{
1414
/// <summary>
15-
/// A type that can be used to exchange messages between different objects.
16-
/// This can be useful to decouple different modules of an application without having to keep strong
17-
/// references to types being referenced. It is also possible to send messages to specific channels, uniquely
18-
/// identified by a token, and to have different messengers in different sections of an applications.
19-
/// In order to use the <see cref="IMessenger"/> functionalities, first define a message type, like so:
20-
/// <code>
21-
/// public sealed class LoginCompletedMessage { }
22-
/// </code>
23-
/// Then, register your a recipient for this message:
24-
/// <code>
25-
/// Messenger.Default.Register&lt;LoginCompletedMessage&gt;(this, (r, m) =>
26-
/// {
27-
/// // Handle the message here...
28-
/// });
29-
/// </code>
30-
/// The message handler here is a lambda expression taking two parameters: the recipient and the message.
31-
/// This is done to avoid the allocations for the closures that would've been generated if the expression
32-
/// had captured the current instance - instead it is possible to just cast the recipient to the right type
33-
/// and access private instance members from the handler directly. This allows the message handler to be a
34-
/// static method, which enables the C# to perform a number of additional memory optimizations.
35-
/// Finally, send a message when needed, like so:
36-
/// <code>
37-
/// Messenger.Default.Send&lt;LoginCompletedMessage&gt;();
38-
/// </code>
39-
/// Additionally, the method group syntax can also be used to specify the message handler
40-
/// to invoke when receiving a message, if a method with the right signature is available
41-
/// in the current scope. This is helpful to keep the registration and handling logic separate.
42-
/// Following up from the previous example, consider a class having this method:
43-
/// <code>
44-
/// private static void Receive(object recipient, LoginCompletedMessage message)
45-
/// {
46-
/// // Handle the message there
47-
/// }
48-
/// </code>
49-
/// The registration can then be performed in a single line like so:
50-
/// <code>
51-
/// Messenger.Default.Register&lt;LoginCompletedMessage&gt;(this, Receive);
52-
/// </code>
53-
/// The C# compiler will automatically convert that expression to a <see cref="MessageHandler{TRecipient,TMessage}"/> instance
54-
/// compatible with <see cref="MessengerExtensions.Register{TRecipient,TMessage}(IMessenger,TRecipient,MessageHandler{TRecipient,TMessage})"/>.
55-
/// This will also work if multiple overloads of that method are available, each handling a different
56-
/// message type: the C# compiler will automatically pick the right one for the current message type.
57-
/// For info on the other available features, check the <see cref="IMessenger"/> interface.
15+
/// A class providing a reference implementation for the <see cref="IMessenger"/> interface.
5816
/// </summary>
17+
/// <remarks>
18+
/// This <see cref="IMessenger"/> implementation uses strong references to track the registered
19+
/// recipients, so it is necessary to manually unregister them when they're no longer needed.
20+
/// </remarks>
5921
public sealed class Messenger : IMessenger
6022
{
6123
// The Messenger class uses the following logic to link stored instances together:

0 commit comments

Comments
 (0)