using System; using ArchestrA.MxAccess; namespace MxGateway.Worker.MxAccess; /// /// Adapter exposing MXAccess COM object methods through the /// interface. /// /// /// The supplied object must implement the typed MXAccess COM interface contract. /// In production it is the LMXProxyServerClass RCW, which implements /// / / /// . Tests substitute a typed fake that /// implements directly. The earlier late-bound /// Type.InvokeMember reflection fallback was removed: it bypassed the /// typed interface contract, boxed value-type handles on every call, and only /// ever served test doubles — a typed fake is the supported test seam now. /// public sealed class MxAccessComServer : IMxAccessServer { private readonly object mxAccessComObject; /// /// Initializes the adapter with the MXAccess COM object. /// /// /// MXAccess COM object instance. Must implement either the typed /// COM interface family (production) or /// directly (test fakes). /// public MxAccessComServer(object mxAccessComObject) { this.mxAccessComObject = mxAccessComObject ?? throw new ArgumentNullException(nameof(mxAccessComObject)); } /// public int Register(string clientName) { if (mxAccessComObject is IMxAccessServer typedFake) { return typedFake.Register(clientName); } return AsProxyServer().Register(clientName); } /// public void Unregister(int serverHandle) { if (mxAccessComObject is IMxAccessServer typedFake) { typedFake.Unregister(serverHandle); return; } AsProxyServer().Unregister(serverHandle); } /// public int AddItem( int serverHandle, string itemDefinition) { if (mxAccessComObject is IMxAccessServer typedFake) { return typedFake.AddItem(serverHandle, itemDefinition); } return AsProxyServer().AddItem(serverHandle, itemDefinition); } /// public int AddItem2( int serverHandle, string itemDefinition, string itemContext) { if (mxAccessComObject is IMxAccessServer typedFake) { return typedFake.AddItem2(serverHandle, itemDefinition, itemContext); } return AsProxyServer3().AddItem2(serverHandle, itemDefinition, itemContext); } /// public void RemoveItem( int serverHandle, int itemHandle) { if (mxAccessComObject is IMxAccessServer typedFake) { typedFake.RemoveItem(serverHandle, itemHandle); return; } AsProxyServer().RemoveItem(serverHandle, itemHandle); } /// public void Advise( int serverHandle, int itemHandle) { if (mxAccessComObject is IMxAccessServer typedFake) { typedFake.Advise(serverHandle, itemHandle); return; } AsProxyServer().Advise(serverHandle, itemHandle); } /// public void UnAdvise( int serverHandle, int itemHandle) { if (mxAccessComObject is IMxAccessServer typedFake) { typedFake.UnAdvise(serverHandle, itemHandle); return; } AsProxyServer().UnAdvise(serverHandle, itemHandle); } /// public void AdviseSupervisory( int serverHandle, int itemHandle) { if (mxAccessComObject is IMxAccessServer typedFake) { typedFake.AdviseSupervisory(serverHandle, itemHandle); return; } AsProxyServer4().AdviseSupervisory(serverHandle, itemHandle); } /// public void Write( int serverHandle, int itemHandle, object? value, int userId) { if (mxAccessComObject is IMxAccessServer typedFake) { typedFake.Write(serverHandle, itemHandle, value, userId); return; } AsProxyServer().Write(serverHandle, itemHandle, value!, userId); } /// public void Write2( int serverHandle, int itemHandle, object? value, object? timestamp, int userId) { if (mxAccessComObject is IMxAccessServer typedFake) { typedFake.Write2(serverHandle, itemHandle, value, timestamp, userId); return; } AsProxyServer4().Write2(serverHandle, itemHandle, value!, timestamp!, userId); } /// public void WriteSecured( int serverHandle, int itemHandle, int currentUserId, int verifierUserId, object? value) { if (mxAccessComObject is IMxAccessServer typedFake) { typedFake.WriteSecured(serverHandle, itemHandle, currentUserId, verifierUserId, value); return; } AsProxyServer().WriteSecured(serverHandle, itemHandle, currentUserId, verifierUserId, value!); } /// public void WriteSecured2( int serverHandle, int itemHandle, int currentUserId, int verifierUserId, object? value, object? timestamp) { if (mxAccessComObject is IMxAccessServer typedFake) { typedFake.WriteSecured2(serverHandle, itemHandle, currentUserId, verifierUserId, value, timestamp); return; } AsProxyServer4().WriteSecured2(serverHandle, itemHandle, currentUserId, verifierUserId, value!, timestamp!); } private ILMXProxyServer AsProxyServer() { return mxAccessComObject as ILMXProxyServer ?? throw new InvalidOperationException( $"MXAccess COM object of type '{mxAccessComObject.GetType().FullName}' does not implement " + $"{nameof(ILMXProxyServer)} or {nameof(IMxAccessServer)}."); } private ILMXProxyServer3 AsProxyServer3() { return mxAccessComObject as ILMXProxyServer3 ?? throw new InvalidOperationException( $"MXAccess COM object of type '{mxAccessComObject.GetType().FullName}' does not implement " + $"{nameof(ILMXProxyServer3)} or {nameof(IMxAccessServer)}."); } private ILMXProxyServer4 AsProxyServer4() { return mxAccessComObject as ILMXProxyServer4 ?? throw new InvalidOperationException( $"MXAccess COM object of type '{mxAccessComObject.GetType().FullName}' does not implement " + $"{nameof(ILMXProxyServer4)} or {nameof(IMxAccessServer)}."); } }