using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using ScadaLink.Commons.Interfaces.Protocol; using ScadaLink.DataConnectionLayer.Adapters; namespace ScadaLink.DataConnectionLayer; /// /// WP-34: Default factory that resolves protocol type strings to IDataConnection adapters. /// Protocol extensibility: register new adapters via the constructor or AddAdapter method. /// public class DataConnectionFactory : IDataConnectionFactory { private readonly Dictionary, IDataConnection>> _factories = new(StringComparer.OrdinalIgnoreCase); private readonly ILoggerFactory _loggerFactory; public DataConnectionFactory(ILoggerFactory loggerFactory) : this(loggerFactory, Options.Create(new OpcUaGlobalOptions())) { } public DataConnectionFactory(ILoggerFactory loggerFactory, IOptions opcUaGlobalOptions) { _loggerFactory = loggerFactory; var globalOptions = opcUaGlobalOptions.Value; // Register built-in protocols. // DataConnectionLayer-014: pass the ILoggerFactory into RealOpcUaClientFactory so // the RealOpcUaClient it builds gets a real logger — without it the DCL-012 // auto-accept-certificate security warning is silently discarded by NullLogger. RegisterAdapter("OpcUa", details => new OpcUaDataConnection( new RealOpcUaClientFactory(globalOptions, _loggerFactory), _loggerFactory.CreateLogger())); } /// /// Registers a new protocol adapter factory. This is the extension point /// for adding new protocols without modifying existing code. /// public void RegisterAdapter(string protocolType, Func, IDataConnection> factory) { _factories[protocolType] = factory; } public IDataConnection Create(string protocolType, IDictionary connectionDetails) { if (!_factories.TryGetValue(protocolType, out var factory)) throw new ArgumentException($"Unknown protocol type: {protocolType}. Registered protocols: {string.Join(", ", _factories.Keys)}"); return factory(connectionDetails); } }