using System.Net; using System.Net.Sockets; using System.Reflection; using qmonlib.Attributes; using Quadarax.Foundation.Core.Object; using Quadarax.Foundation.Core.Reflection.Extensions; namespace qmonlib { public class QMonClient : DisposableObject { #region *** Properties *** public bool IsEnabled { get => _isEnabled; set { SetEnabled(value); } } public string InstanceIdentifier { get; } #endregion #region *** Fields *** private bool _isEnabled; private QMonConfiuration _configuration; private UdpClient? _udpClientGeneral; private UdpClient? _udpClientData; private Timer? _timerGeneral; private Timer? _timerData; private IDictionary _generalCache = new Dictionary(); #endregion #region *** Constructors *** public QMonClient(string instanceIdentifier, QMonConfiuration configuration) { InstanceIdentifier = instanceIdentifier ?? throw new ArgumentNullException(nameof(instanceIdentifier)); _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); SetEnabled(_configuration.Enabled); ScanAssemblies(); } private void ScanAssemblies() { var assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in assemblies) { var types = assembly.GetTypesWithAttribute(true); foreach (var type in types) { var monItemGeneral = new MonItemGeneral { InstanceIdentifier = InstanceIdentifier, Caption = type.GetCustomAttribute()?.Caption ?? type.Name, Description = type.GetCustomAttribute()?.Description ?? string.Empty, ViewType = MonItemGeneral.MonViewType.Item }; var properties = type.GetPropertiesWithAttribute(true); foreach (var property in properties) { var itemDescriptor = new MonItemGeneral.ItemDescriptor { Name = property.Name, TypeName = property.PropertyType.Name, Label = property.GetCustomAttribute()?.Label ?? property.Name, Description = property.GetCustomAttribute()?.Description ?? string.Empty, Order = property.GetCustomAttribute()?.Order ?? 0, _propertyInfo = property }; monItemGeneral.Items.Add(itemDescriptor); } _generalCache.Add(type.FullName!, monItemGeneral); } } } #endregion #region *** Public Operations *** #endregion #region *** Protected Operations *** protected override void OnDisposing() { Close(); _generalCache.Clear(); } private void Open() { if (_udpClientGeneral != null) throw new InvalidOperationException("UDP client channel General already open. Close first."); if (_udpClientData != null) throw new InvalidOperationException("UDP client channel Data already open. Close first."); _udpClientGeneral = CreateUdpClient(_configuration.TargetUriGeneral); _udpClientData = CreateUdpClient(_configuration.TargetUriData); _timerGeneral = new Timer(OnTimerGeneral, this, _configuration.EmitGeneralInterval, _configuration.EmitGeneralInterval); _timerData = new Timer(OnTimerData, this, _configuration.EmitDataInterval, _configuration.EmitDataInterval); } private void OnTimerData(object? state) { throw new NotImplementedException(); } private void OnTimerGeneral(object? state) { throw new NotImplementedException(); } private void Close() { if (_udpClientGeneral != null) { _timerGeneral?.Dispose(); _udpClientGeneral.Close(); _udpClientGeneral.Dispose(); _udpClientGeneral = null; _timerGeneral = null; } if (_udpClientData != null) { _timerData?.Dispose(); _udpClientData.Close(); _udpClientData.Dispose(); _udpClientData = null; _timerData = null; } } private UdpClient CreateUdpClient(Uri targetUri) { var udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(targetUri.DnsSafeHost), targetUri.Port)); return udpClient; } private void SetEnabled(bool value) { if (value == _isEnabled) return; _isEnabled = value; if (_isEnabled) Open(); else Close(); } #endregion #region *** Nested Types *** #endregion } }