The lightweight, high-performance messaging library extracted from the CommunityToolkit.Mvvm project. This library provides a decoupled way for different parts of your application to communicate through messages, supporting both strong and weak reference implementations.
- Decoupled Communication: Send messages between different components without tight coupling
- Multiple Messenger Types: Choose between
StrongReferenceMessengerandWeakReferenceMessenger - Channel Support: Use tokens to create separate communication channels
- Thread-Safe: All operations are thread-safe
- High Performance: Optimized for minimal overhead
- Observable Support: Integration with reactive programming patterns
- Request/Response Patterns: Built-in support for request messages and responses
Install via NuGet Package Manager:
dotnet add package Russkyc.MessagingOr via Package Manager Console:
Install-Package Russkyc.Messagingusing Russkyc.Messaging;
// In your main method or somewhere else
var handler = new MessageHandler();
// Send a message
WeakReferenceMessenger.Default.Send(new UserLoggedInMessage("john_doe"));
// Define a message
public record UserLoggedInMessage(string Username);
// Create a recipient
public class MessageHandler
{
public MessageHandler()
{
// Register to receive messages
WeakReferenceMessenger.Default.Register<UserLoggedInMessage>(this, OnUserLoggedIn);
}
private void OnUserLoggedIn(object recipient, UserLoggedInMessage message)
{
Console.WriteLine($"User {message.Username} logged in!");
}
}// Create a custom messenger instance
var messenger = new WeakReferenceMessenger();
// Create a handler instance
var handler = new MessageHandler();
// Register a recipient
messenger.Register<UserLoggedInMessage>(handler, (recipient, message) =>
{
Console.WriteLine($"Custom messenger: User {message.Username} logged in!");
});
// Send a message
messenger.Send(new UserLoggedInMessage("jane_doe"));// Create a handler for admin messages
var adminHandler = new object();
// Register on a specific channel
WeakReferenceMessenger.Default.Register<UserLoggedInMessage, AdminChannel>(
adminHandler,
new AdminChannel(),
(recipient, message) => Console.WriteLine($"Admin: {message.Username} logged in!"));
// Send to a specific channel
WeakReferenceMessenger.Default.Send(
new UserLoggedInMessage("admin"),
new AdminChannel());
// Define a token for a specific channel
public class AdminChannel { }The library supports both synchronous and asynchronous request/response messaging patterns using RequestMessage<T> and AsyncRequestMessage<T> respectively.
Synchronous requests allow you to send a message and immediately receive a response:
using Russkyc.Messaging;
// Create a handler for requests
var requestHandler = new object();
// Handle the request
WeakReferenceMessenger.Default.Register<GetUserDataRequest>(requestHandler, (recipient, message) =>
{
// Simulate data retrieval
var userData = new UserData { Name = "John Doe", Email = "john@example.com" };
message.Reply(userData);
});
// Send a request and get response
var request = new GetUserDataRequest { UserId = "123" };
var response = WeakReferenceMessenger.Default.Send(request);
Console.WriteLine($"User: {response.Name}, Email: {response.Email}");
// Define a request message
public class GetUserDataRequest : RequestMessage<UserData>
{
public string UserId { get; init; }
}
// Define response data
public class UserData
{
public string Name { get; set; }
public string Email { get; set; }
}Asynchronous requests are useful when the response requires async operations like I/O:
using Russkyc.Messaging;
// Create a handler for async requests
var asyncHandler = new object();
// Handle async request
WeakReferenceMessenger.Default.Register<AsyncDataRequest>(asyncHandler, async (recipient, message) =>
{
// Simulate async data retrieval
await Task.Delay(100); // Simulate async work
var data = "Async data result";
message.Reply(data);
});
// Send async request
var request = new AsyncDataRequest();
var response = await WeakReferenceMessenger.Default.Send(request);
Console.WriteLine($"Data: {response}");
// Define an async request message
public class AsyncDataRequest : AsyncRequestMessage<string> { }- Uses weak references to track recipients
- Recipients are automatically unregistered when garbage collected
- Prevents memory leaks
- Slightly higher overhead due to weak reference management
var messenger = new WeakReferenceMessenger();- Uses strong references to track recipients
- Recipients must be manually unregistered
- Better performance
- Risk of memory leaks if not properly managed
var messenger = new StrongReferenceMessenger();IMessenger: Main interface for messaging functionality
The library provides several built-in message types for different communication patterns:
- RequestMessage: Synchronous request/response messaging. Handlers call
message.Reply(T response)to send a response. - AsyncRequestMessage: Asynchronous request/response messaging. Handlers call
message.Reply(T response)after async operations. - CollectionRequestMessage: Request for collections of data. Handlers call
message.Reply(IEnumerable<T> response). - AsyncCollectionRequestMessage: Asynchronous request for collections. Handlers call
message.Reply(IEnumerable<T> response). - PropertyChangedMessage: Notifies about property changes. Contains
PropertyNameandOldValue/NewValue. - ValueChangedMessage: Notifies about value changes. Contains
OldValueandNewValue.
Register<TMessage>(recipient, handler): Register a message handlerUnregister<TMessage>(recipient): Unregister from a message typeSend<TMessage>(message): Send a message to all registered recipientsIsRegistered<TMessage>(recipient): Check if a recipient is registered
The IMessengerExtensions class provides convenient extension methods for common operations.
- Use
WeakReferenceMessengerfor long-lived applications to prevent memory leaks - Prefer
StrongReferenceMessengerfor short-lived scenarios where performance is critical - Use channels (tokens) to reduce message broadcasting overhead
- Consider the frequency of message sending in performance-critical paths
- Clone the repository
- Ensure you have .NET 8.0 SDK installed
- Run
dotnet buildin the project directory
Contributions are welcome! Please feel free to submit issues and pull requests.
This library is a subset of the messaging functionality from CommunityToolkit.Mvvm, extracted and independently packaged.
The original code is licensed under the MIT License by the .NET Foundation and Contributors.
This project is licensed under the MIT License - see the LICENSE.md file for details.