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);
}
}
}