From be609a513e77142c172f6377f16bb5fa9eae9da9 Mon Sep 17 00:00:00 2001 From: Pierre Arnaud Date: Fri, 30 Jan 2026 13:03:19 +0100 Subject: [PATCH] Refactor: Introduce IFacade interface for SocketIO and SignalR facades - Create IFacade interface defining common API for SocketIO and SignalR - Update SocketIoFacade to implement IFacade - Update SignalRFacade to implement IFacade (add Connect no-op) - Update RuntimeControllerBase.Socket to return IFacade - Update RuntimeControllerAspNetBase.Socket to return IFacade - Update RuntimeControllerDotNetFirst.Socket to return IFacade - Update ElectronNetRuntime.GetSocket() to return IFacade - Update BridgeConnector.Socket to return IFacade This enables polymorphic usage of both facades throughout the codebase and prepares for full Electron API integration with SignalR mode. --- src/ElectronNET.API/Bridge/BridgeConnector.cs | 4 +- src/ElectronNET.API/Bridge/IFacade.cs | 62 +++++++++++++++++++ src/ElectronNET.API/Bridge/SocketIOFacade.cs | 3 +- src/ElectronNET.API/ElectronNetRuntime.cs | 3 +- .../Controllers/RuntimeControllerBase.cs | 3 +- .../RuntimeControllerDotNetFirst.cs | 3 +- .../Bridge/SignalRFacade.cs | 12 +++- .../RuntimeControllerAspNetBase.cs | 3 +- ...ntimeControllerAspNetDotnetFirstSignalR.cs | 10 ++- 9 files changed, 94 insertions(+), 9 deletions(-) create mode 100644 src/ElectronNET.API/Bridge/IFacade.cs diff --git a/src/ElectronNET.API/Bridge/BridgeConnector.cs b/src/ElectronNET.API/Bridge/BridgeConnector.cs index 3c06b43..0835992 100644 --- a/src/ElectronNET.API/Bridge/BridgeConnector.cs +++ b/src/ElectronNET.API/Bridge/BridgeConnector.cs @@ -2,9 +2,11 @@ // ReSharper disable once CheckNamespace namespace ElectronNET.API { + using ElectronNET.API.Bridge; + internal static class BridgeConnector { - public static SocketIoFacade Socket + public static IFacade Socket { get { diff --git a/src/ElectronNET.API/Bridge/IFacade.cs b/src/ElectronNET.API/Bridge/IFacade.cs new file mode 100644 index 0000000..c3ae754 --- /dev/null +++ b/src/ElectronNET.API/Bridge/IFacade.cs @@ -0,0 +1,62 @@ +namespace ElectronNET.API.Bridge +{ + using System; + using System.Threading.Tasks; + + /// + /// Common interface for communication facades (SocketIO and SignalR). + /// Provides methods for bidirectional communication between .NET and Electron. + /// + internal interface IFacade + { + /// + /// Raised when the bridge connection is established. + /// + event EventHandler BridgeConnected; + + /// + /// Raised when the bridge connection is lost. + /// + event EventHandler BridgeDisconnected; + + /// + /// Establishes the connection to Electron. + /// + void Connect(); + + /// + /// Registers a persistent event handler. + /// + void On(string eventName, Action action); + + /// + /// Registers a persistent event handler with a typed parameter. + /// + void On(string eventName, Action action); + + /// + /// Registers a one-time event handler. + /// + void Once(string eventName, Action action); + + /// + /// Registers a one-time event handler with a typed parameter. + /// + void Once(string eventName, Action action); + + /// + /// Removes an event handler. + /// + void Off(string eventName); + + /// + /// Sends a message to Electron. + /// + Task Emit(string eventName, params object[] args); + + /// + /// Disposes the connection. + /// + void DisposeSocket(); + } +} diff --git a/src/ElectronNET.API/Bridge/SocketIOFacade.cs b/src/ElectronNET.API/Bridge/SocketIOFacade.cs index 4db0a0b..58f0fef 100644 --- a/src/ElectronNET.API/Bridge/SocketIOFacade.cs +++ b/src/ElectronNET.API/Bridge/SocketIOFacade.cs @@ -4,11 +4,12 @@ namespace ElectronNET.API; using System; using System.Threading.Tasks; +using ElectronNET.API.Bridge; using ElectronNET.API.Serialization; using SocketIO.Serializer.SystemTextJson; using SocketIO = SocketIOClient.SocketIO; -internal class SocketIoFacade +internal class SocketIoFacade : IFacade { private readonly SocketIO _socket; private readonly object _lockObj = new object(); diff --git a/src/ElectronNET.API/ElectronNetRuntime.cs b/src/ElectronNET.API/ElectronNetRuntime.cs index 78d976e..e04f5a0 100644 --- a/src/ElectronNET.API/ElectronNetRuntime.cs +++ b/src/ElectronNET.API/ElectronNetRuntime.cs @@ -1,6 +1,7 @@ namespace ElectronNET { using ElectronNET.API; + using ElectronNET.API.Bridge; using ElectronNET.Runtime; using ElectronNET.Runtime.Controllers; using ElectronNET.Runtime.Data; @@ -49,7 +50,7 @@ internal static Func OnAppReadyCallback { get; set; } - internal static SocketIoFacade GetSocket() + internal static IFacade GetSocket() { return RuntimeControllerCore?.Socket; } diff --git a/src/ElectronNET.API/Runtime/Controllers/RuntimeControllerBase.cs b/src/ElectronNET.API/Runtime/Controllers/RuntimeControllerBase.cs index fe527c7..510e845 100644 --- a/src/ElectronNET.API/Runtime/Controllers/RuntimeControllerBase.cs +++ b/src/ElectronNET.API/Runtime/Controllers/RuntimeControllerBase.cs @@ -1,6 +1,7 @@ namespace ElectronNET.Runtime.Controllers { using ElectronNET.API; + using ElectronNET.API.Bridge; using ElectronNET.Runtime.Services; using ElectronNET.Runtime.Services.ElectronProcess; using ElectronNET.Runtime.Services.SocketBridge; @@ -12,7 +13,7 @@ { } - internal abstract SocketIoFacade Socket { get; } + internal abstract IFacade Socket { get; } internal abstract ElectronProcessBase ElectronProcess { get; } diff --git a/src/ElectronNET.API/Runtime/Controllers/RuntimeControllerDotNetFirst.cs b/src/ElectronNET.API/Runtime/Controllers/RuntimeControllerDotNetFirst.cs index 7059167..d5e37a7 100644 --- a/src/ElectronNET.API/Runtime/Controllers/RuntimeControllerDotNetFirst.cs +++ b/src/ElectronNET.API/Runtime/Controllers/RuntimeControllerDotNetFirst.cs @@ -1,6 +1,7 @@ namespace ElectronNET.Runtime.Controllers { using ElectronNET.API; + using ElectronNET.API.Bridge; using ElectronNET.Common; using ElectronNET.Runtime.Data; using ElectronNET.Runtime.Helpers; @@ -19,7 +20,7 @@ { } - internal override SocketIoFacade Socket + internal override IFacade Socket { get { diff --git a/src/ElectronNET.AspNet/Bridge/SignalRFacade.cs b/src/ElectronNET.AspNet/Bridge/SignalRFacade.cs index be41270..54216d9 100644 --- a/src/ElectronNET.AspNet/Bridge/SignalRFacade.cs +++ b/src/ElectronNET.AspNet/Bridge/SignalRFacade.cs @@ -4,13 +4,14 @@ namespace ElectronNET.API using System.Collections.Concurrent; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; + using ElectronNET.API.Bridge; using ElectronNET.AspNet.Hubs; /// /// SignalR-based facade that mimics the SocketIoFacade interface /// for compatibility with existing Electron API code. /// - internal class SignalRFacade + internal class SignalRFacade : IFacade { private readonly IHubContext _hubContext; private string _connectionId; @@ -26,6 +27,15 @@ namespace ElectronNET.API public event EventHandler BridgeDisconnected; public event EventHandler BridgeConnected; + /// + /// SignalR connections are managed by ASP.NET Core, so this is a no-op. + /// Connection establishment happens via the ElectronHub. + /// + public void Connect() + { + // No-op: SignalR connection is managed by ASP.NET Core + } + public void SetConnectionId(string connectionId) { _connectionId = connectionId; diff --git a/src/ElectronNET.AspNet/Runtime/Controllers/RuntimeControllerAspNetBase.cs b/src/ElectronNET.AspNet/Runtime/Controllers/RuntimeControllerAspNetBase.cs index 65487df..b5478f9 100644 --- a/src/ElectronNET.AspNet/Runtime/Controllers/RuntimeControllerAspNetBase.cs +++ b/src/ElectronNET.AspNet/Runtime/Controllers/RuntimeControllerAspNetBase.cs @@ -3,6 +3,7 @@ using System; using System.Threading.Tasks; using ElectronNET.API; + using ElectronNET.API.Bridge; using ElectronNET.Common; using ElectronNET.Runtime.Controllers; using ElectronNET.Runtime.Data; @@ -25,7 +26,7 @@ internal override SocketBridgeService SocketBridge => this.socketBridge; - internal override SocketIoFacade Socket + internal override IFacade Socket { get { diff --git a/src/ElectronNET.AspNet/Runtime/Controllers/RuntimeControllerAspNetDotnetFirstSignalR.cs b/src/ElectronNET.AspNet/Runtime/Controllers/RuntimeControllerAspNetDotnetFirstSignalR.cs index b392d00..78008ec 100644 --- a/src/ElectronNET.AspNet/Runtime/Controllers/RuntimeControllerAspNetDotnetFirstSignalR.cs +++ b/src/ElectronNET.AspNet/Runtime/Controllers/RuntimeControllerAspNetDotnetFirstSignalR.cs @@ -4,6 +4,7 @@ namespace ElectronNET.AspNet.Runtime using System.Linq; using System.Threading.Tasks; using ElectronNET.API; + using ElectronNET.API.Bridge; using ElectronNET.Common; using ElectronNET.Runtime.Data; using ElectronNET.Runtime.Services.ElectronProcess; @@ -44,11 +45,16 @@ namespace ElectronNET.AspNet.Runtime internal override ElectronProcessBase ElectronProcess => this.electronProcess; internal override SocketBridgeService SocketBridge => null; - internal override SocketIoFacade Socket + internal override IFacade Socket { get { - throw new NotImplementedException("SignalR mode uses SignalRFacade"); + if (this.State == LifetimeState.Ready) + { + return this.signalRFacade; + } + + throw new Exception("Cannot access SignalR facade. Runtime is not in 'Ready' state"); } }