An open API service indexing awesome lists of open source software.

https://github.com/russkyc/messaging

The lightweight, high-performance messaging library extracted from the CommunityToolkit.Mvvm project
https://github.com/russkyc/messaging

community-toolkit events messaging mvvm pubsub subscription

Last synced: 5 months ago
JSON representation

The lightweight, high-performance messaging library extracted from the CommunityToolkit.Mvvm project

Awesome Lists containing this project

README

          



Russkyc.Messaging - Independently packaged Messaging subset from CommunityToolkit.MVVM







Nuget

The lightweight, high-performance messaging library extracted from the [CommunityToolkit.Mvvm](https://github.com/CommunityToolkit/dotnet) project. This library provides a decoupled way for different parts of your application to communicate through messages, supporting both strong and weak reference implementations.

## Features

- **Decoupled Communication**: Send messages between different components without tight coupling
- **Multiple Messenger Types**: Choose between `StrongReferenceMessenger` and `WeakReferenceMessenger`
- **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

## Installation

Install via NuGet Package Manager:

```bash
dotnet add package Russkyc.Messaging
```

Or via Package Manager Console:

```powershell
Install-Package Russkyc.Messaging
```

## Quick Start

### Basic Usage

```csharp
using 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(this, OnUserLoggedIn);
}

private void OnUserLoggedIn(object recipient, UserLoggedInMessage message)
{
Console.WriteLine($"User {message.Username} logged in!");
}
}
```

### Using Custom Messengers

```csharp
// Create a custom messenger instance
var messenger = new WeakReferenceMessenger();

// Create a handler instance
var handler = new MessageHandler();

// Register a recipient
messenger.Register(handler, (recipient, message) =>
{
Console.WriteLine($"Custom messenger: User {message.Username} logged in!");
});

// Send a message
messenger.Send(new UserLoggedInMessage("jane_doe"));
```

### Using Channels (Tokens)

```csharp
// Create a handler for admin messages
var adminHandler = new object();

// Register on a specific channel
WeakReferenceMessenger.Default.Register(
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 { }

```

## Request/Response Patterns

The library supports both synchronous and asynchronous request/response messaging patterns using `RequestMessage` and `AsyncRequestMessage` respectively.

### Synchronous Requests

Synchronous requests allow you to send a message and immediately receive a response:

```csharp
using Russkyc.Messaging;

// Create a handler for requests
var requestHandler = new object();

// Handle the request
WeakReferenceMessenger.Default.Register(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
{
public string UserId { get; init; }
}

// Define response data
public class UserData
{
public string Name { get; set; }
public string Email { get; set; }
}
```

### Asynchronous Requests

Asynchronous requests are useful when the response requires async operations like I/O:

```csharp
using Russkyc.Messaging;

// Create a handler for async requests
var asyncHandler = new object();

// Handle async request
WeakReferenceMessenger.Default.Register(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 { }
```

## Messenger Types

### WeakReferenceMessenger (Recommended)

- Uses weak references to track recipients
- Recipients are automatically unregistered when garbage collected
- Prevents memory leaks
- Slightly higher overhead due to weak reference management

```csharp
var messenger = new WeakReferenceMessenger();
```

### StrongReferenceMessenger

- Uses strong references to track recipients
- Recipients must be manually unregistered
- Better performance
- Risk of memory leaks if not properly managed

```csharp
var messenger = new StrongReferenceMessenger();
```

## API Reference

### Core Interfaces

- `IMessenger`: Main interface for messaging functionality

### Message Types

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 response)`.
- **AsyncCollectionRequestMessage**: Asynchronous request for collections. Handlers call `message.Reply(IEnumerable response)`.
- **PropertyChangedMessage**: Notifies about property changes. Contains `PropertyName` and `OldValue`/`NewValue`.
- **ValueChangedMessage**: Notifies about value changes. Contains `OldValue` and `NewValue`.

### Key Methods

- `Register(recipient, handler)`: Register a message handler
- `Unregister(recipient)`: Unregister from a message type
- `Send(message)`: Send a message to all registered recipients
- `IsRegistered(recipient)`: Check if a recipient is registered

### Extension Methods

The `IMessengerExtensions` class provides convenient extension methods for common operations.

## Performance Considerations

- Use `WeakReferenceMessenger` for long-lived applications to prevent memory leaks
- Prefer `StrongReferenceMessenger` for 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

## Building from Source

1. Clone the repository
2. Ensure you have .NET 8.0 SDK installed
3. Run `dotnet build` in the project directory

## Contributing

Contributions are welcome! Please feel free to submit issues and pull requests.

## Credits

This library is a subset of the messaging functionality from [CommunityToolkit.Mvvm](https://github.com/CommunityToolkit/dotnet), extracted and independently packaged.

The original code is licensed under the MIT License by the .NET Foundation and Contributors.

## License

This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.