using DeviceService.Core; using DeviceService.Logging; using System.Reflection; namespace DeviceService.Device { /// /// 设备信息持久化辅助:负责设备信息与 Config\Devices.db 之间的读写。 /// DeviceManager 只负责服务正式启动后的设备管理,数据库读写一律经由本类。 /// public static class DeviceHelper { private static readonly object _scanSync = new object(); private static readonly Dictionary _deviceTypeMap = new Dictionary(StringComparer.Ordinal); /// /// 扫描到的设备类型列表(取自 DeviceDescAttribute.Type)。 /// 程序启动后调用 填充。 /// public static List AllDeviceType { get; } = new List(); public static List AllDevices { get; } = new List(); /// /// 扫描本程序集中所有标注了 且继承 的类, /// 将注解中的 Type 存入 ,并记录 Type 到设备类的映射。 /// public static void ScanDeviceTypes() { lock (_scanSync) { AllDeviceType.Clear(); _deviceTypeMap.Clear(); IEnumerable types; try { types = Assembly.GetExecutingAssembly().GetTypes(); } catch (ReflectionTypeLoadException ex) { types = ex.Types; } foreach (Type? t in types) { if (t == null || !typeof(IDevice).IsAssignableFrom(t) || t.IsAbstract) { continue; } DeviceDescAttribute? attr = t.GetCustomAttribute(false); if (attr == null || string.IsNullOrEmpty(attr.Type)) { continue; } _deviceTypeMap[attr.Type] = t; AllDeviceType.Add(attr.Type); } } } /// 按注解 Type 创建对应的设备实例。 public static bool TryCreateDevice(string type, out IDevice? device) { device = null; lock (_scanSync) { if (type == null || !_deviceTypeMap.TryGetValue(type, out Type? deviceType)) { return false; } device = (IDevice?)Activator.CreateInstance(deviceType); return device != null; } } /// /// 保存设备信息到 Config\Devices.db(仅持久化,不调用 Init、不影响 DeviceManager 的内存集合)。 /// 返回是否保存成功;新增记录会回填自增 Id。 /// public static bool SaveDevice(IDevice device) { if (device == null) throw new ArgumentNullException(nameof(device)); // 写入 Config\Devices.db,下次启动时据此恢复设备列表;新增记录回填自增 Id long id = DeviceDatabase.Instance.Save(ToRecord(device)); if (id > 0) { TrySet(device, nameof(IDevice.Id), id); } return id > 0; } /// /// 从 Config\Devices.db 读取全部设备并创建实例(不调用 Init、不加入任何集合)。 /// 调用方按需加入 DeviceManager,服务正式启动后再逐一 。 /// public static IReadOnlyList LoadDevices() { var devices = new List(); AllDevices.Clear(); foreach (DeviceRecord record in DeviceDatabase.Instance.LoadAll()) { if (string.IsNullOrWhiteSpace(record.DeviceId) || string.IsNullOrWhiteSpace(record.Type)) { continue; } if (!DeviceHelper.TryCreateDevice(record.Type, out IDevice? device) || device == null) { GlobalLogger.Logger.Warn("DeviceHelper", $"[设备库] 未知设备类型 {record.Type},已跳过 {record.DeviceId}"); continue; } ApplyRecord(device, record); devices.Add(device); AllDevices.Add(device); } return devices; } /// 从 Config\Devices.db 删除设备记录。 public static void RemoveDevice(string deviceId) { DeviceDatabase.Instance.Remove(deviceId); } private static DeviceRecord ToRecord(IDevice device) { return new DeviceRecord { Id = device.Id, DeviceId = device.DeviceId ?? string.Empty, Type = device.Type ?? string.Empty, Brand = device.Brand ?? string.Empty, ConnectStr = device.ConnectStr ?? string.Empty, AccessType = device.AccessType }; } /// IDevice 接口只暴露 getter,实现类一般有 setter,通过反射回填。 private static void ApplyRecord(IDevice device, DeviceRecord record) { TrySet(device, nameof(IDevice.Id), record.Id); TrySet(device, nameof(IDevice.DeviceId), record.DeviceId); TrySet(device, nameof(IDevice.Brand), record.Brand); TrySet(device, nameof(IDevice.ConnectStr), record.ConnectStr); TrySet(device, nameof(IDevice.AccessType), record.AccessType); } private static void TrySet(object target, string propertyName, object value) { PropertyInfo? property = target.GetType().GetProperty(propertyName); if (property == null || !property.CanWrite || !property.PropertyType.IsInstanceOfType(value)) { return; } property.SetValue(target, value); } } }