Files
ClientApiPoC/Shared/SignalR/TunnelClient.cs
2026-03-13 10:23:47 +01:00

84 lines
3.0 KiB
C#

using Microsoft.AspNetCore.SignalR.Client;
namespace ClientApiPoC.Shared.SignalR {
public class TunnelClient : NotifyPropertyChangedBase, IDisposable, IAsyncDisposable {
#region IDisposable-Implementierung
private bool _disposed;
protected virtual void Dispose(bool disposing) {
if (!_disposed) {
if (disposing) {
_ = this.DisposeAsync();
}
_disposed = true;
}
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
public async ValueTask DisposeAsync() {
await DisconnectAsync();
}
#endregion
private HubConnection? _connection = null;
public bool IsConnected => (this.ConnectionState == HubConnectionState.Connected);
public bool IsConnecting => (this.ConnectionState == HubConnectionState.Connecting || this.ConnectionState == HubConnectionState.Reconnecting);
protected HubConnectionState ConnectionState => (_connection?.State ?? HubConnectionState.Disconnected);
public async Task ConnectAsync(string url, Action<HubConnection> configureConnection) {
try {
if (string.IsNullOrWhiteSpace(url)) throw new ArgumentNullException(nameof(url));
if (this.IsConnected) throw new InvalidOperationException("SignalR connection is already established.");
_connection = new HubConnectionBuilder().WithUrl(url).WithAutomaticReconnect().Build();
_connection.Reconnecting += Connection_Reconnecting;
_connection.Reconnected += Connection_Reconnected;
_connection.Closed += Connection_Closed;
configureConnection(_connection);
await _connection.StartAsync();
} finally {
await UpdateStateAsync();
}
}
public async Task DisconnectAsync() {
try {
if (_connection == null) return;
try {
if (this.IsConnected) await _connection.StopAsync();
} catch { }
_connection.Reconnecting -= Connection_Reconnecting;
_connection.Reconnected -= Connection_Reconnected;
_connection.Closed -= Connection_Closed;
await _connection.DisposeAsync();
_connection = null;
} finally {
await UpdateStateAsync();
}
}
private async Task Connection_Reconnecting(Exception? arg) {
await UpdateStateAsync();
}
private async Task Connection_Reconnected(string? arg) {
await UpdateStateAsync();
}
private async Task Connection_Closed(Exception? arg) {
await UpdateStateAsync();
}
private async Task UpdateStateAsync() {
OnPropertyChanged(nameof(IsConnected));
OnPropertyChanged(nameof(IsConnecting));
await Task.CompletedTask;
}
}
}