What is SignalRGen
?
SignalRGen
is a source generator library for .NET that transforms the way you work with SignalR, Microsoft's real-time communication framework. It eliminates boilerplate code and provides a strongly-typed, developer-friendly experience.
The Problem SignalRGen
Solves
Traditional SignalR client implementation requires:
- Writing repetitive connection management code
- Using string-based method names (prone to typos)
- Creating custom wrapper classes for type safety
- Implementing your own reconnection logic
This leads to verbose, error-prone code challenging to maintain as your application grows.
How SignalRGen
Works
SignalRGen
takes a different approach:
- Define Once: Create a simple interface that defines your SignalR contract
- Generate Automatically: The source generator creates a complete client implementation
- Use Anywhere: Register via dependency injection and use the strongly-typed client
No more string-based method names, manual connection handling, or tedious boilerplate!
Key Features
- Zero Runtime Dependencies: All code is generated at build time
- Strongly-Typed Communication: Full IntelliSense support and compile-time safety
- Modern .NET Integration: Seamless dependency injection support
- Automatic Reconnection: Built-in resilient connection handling
- Full Customization: Configure every aspect of the SignalR connection when needed
Example: The SignalRGen
Difference
Traditional SignalR Implementation
With traditional SignalR, you need to manage connections manually, use string-based method names, and implement your own type-safe wrappers:
csharp
// Traditional approach - lots of boilerplate and string-based APIs
public class ChatClient : IAsyncDisposable
{
private readonly HubConnection _connection;
private bool _isConnected;
public ChatClient(string baseUrl)
{
// Manually create and configure connection
_connection = new HubConnectionBuilder()
.WithUrl($"{baseUrl}/chathub")
.WithAutomaticReconnect()
.Build();
// String-based method registration - prone to typos!
_connection.On<string, string>("ReceiveMessage", HandleMessage);
// Manual connection state management
_connection.Closed += async (error) => {
_isConnected = false;
await ReconnectWithRetryAsync();
};
}
// Event to expose the received messages
public event Action<string, string> MessageReceived;
private Task HandleMessage(string user, string message)
{
MessageReceived?.Invoke(user, message);
return Task.CompletedTask;
}
// Complex connection management
public async Task ConnectAsync()
{
if (_isConnected) return;
await _connection.StartAsync();
_isConnected = true;
}
// Custom reconnection logic
private async Task ReconnectWithRetryAsync()
{
// Implement complex retry logic
// ...
}
// String-based method invocation - no compile-time safety!
public async Task SendMessageAsync(string message)
{
if (!_isConnected) await ConnectAsync();
await _connection.InvokeAsync("SendMessage", message);
}
public async ValueTask DisposeAsync()
{
await _connection.DisposeAsync();
}
}
// Usage requires manual instantiation and management
var client = new ChatClient("https://example.com");
await client.ConnectAsync();
client.MessageReceived += (user, message) => Console.WriteLine($"{user}: {message}");
await client.SendMessageAsync("Hello world");
SignalRGen
Implementation
With SignalRGen
, you only need to define a simple interface, and everything else is generated for you:
csharp
// 1. Define your hub interface - that's it!
[HubClient(HubUri = "chathub")]
public interface IChatHub
{
// Server-to-client methods
Task ReceiveMessage(string user, string message);
// Client-to-server methods
[ClientToServerMethod]
Task SendMessage(string message);
}
// 2. Register in your DI container
services.AddSignalRHubs(c => c.HubBaseUri = new Uri("https://example.com"))
.WithChatHub();
// 3. Use the generated client with full type safety
public class ChatService
{
private readonly ChatHub _hub;
// Just inject and use!
public ChatService(ChatHub hub)
{
_hub = hub;
// Strongly-typed event subscription
_hub.OnReceiveMessage += (user, message) => {
Console.WriteLine($"{user}: {message}");
return Task.CompletedTask;
};
}
// Connection management handled automatically
public async Task SendMessageAsync(string message)
{
// Strongly-typed method invocation
await _hub.InvokeSendMessageAsync(message);
}
}
Who Should Use SignalRGen
?
- .NET developers building real-time applications with SignalR
- Teams seeking to reduce boilerplate code and improve maintainability
- Projects that need type-safe, reliable real-time communication
- Teams that want to easily package and share SignalR clients as NuGet packages across multiple projects