using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.IO;
namespace DeviceService.Driver
{
///
/// 驱动信息 SQLite 持久化:数据库文件位于 应用根目录\Config\Drivers.db。
///
/// 表结构:
/// - DriverPackage:已加载的驱动包(Driver 根目录下的一个子文件夹)
/// - DriverType:驱动包内带 [DriverDesc] 注解的驱动类型((类型, 品牌) 定位)
///
/// 所有操作失败仅通过 log 上报,不会中断驱动加载流程。
///
public sealed class DriverDatabase
{
private static readonly object _staticSync = new object();
private static DriverDatabase _instance;
public static DriverDatabase Instance
{
get
{
lock (_staticSync)
{
return _instance ??= new DriverDatabase();
}
}
}
/// 配置目录:应用根目录\Config。
public static string ConfigDirectory =>
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config");
/// 数据库文件路径。
public static string DatabasePath =>
Path.Combine(ConfigDirectory, "Drivers.db");
private readonly object _sync = new object();
private bool _initialized;
private DriverDatabase()
{
}
/// 确保 Config 目录与库表结构存在。失败返回 false 并通过 log 上报。
private bool EnsureReady(Action log)
{
if (_initialized)
{
return true;
}
try
{
if (!Directory.Exists(ConfigDirectory))
{
Directory.CreateDirectory(ConfigDirectory);
}
using (var conn = Open())
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = @"
CREATE TABLE IF NOT EXISTS DriverPackage (
Folder TEXT PRIMARY KEY,
Directory TEXT NOT NULL,
AssemblyCount INTEGER NOT NULL DEFAULT 0,
ScanTime TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS DriverType (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
PackageFolder TEXT NOT NULL,
AssemblyFile TEXT NOT NULL,
FullName TEXT NOT NULL,
DriverType TEXT,
Brand TEXT,
UNIQUE(PackageFolder, FullName)
);
CREATE INDEX IF NOT EXISTS IX_DriverType_Type_Brand ON DriverType(DriverType, Brand);";
cmd.ExecuteNonQuery();
}
_initialized = true;
return true;
}
catch (Exception ex)
{
log?.Invoke($"[驱动库] 初始化失败({DatabasePath}): {ex.Message}");
return false;
}
}
private SQLiteConnection Open()
{
var conn = new SQLiteConnection($"Data Source={DatabasePath};Version=3;");
conn.Open();
return conn;
}
/// 写入(覆盖)一个驱动包及其内部全部驱动类型的记录。
public void SavePackage(DriverPackage package, Action log = null)
{
if (package == null)
{
return;
}
if (!EnsureReady(log))
{
return;
}
try
{
lock (_sync)
{
using (var conn = Open())
using (var tx = conn.BeginTransaction())
{
ExecuteNonQuery(conn, "DELETE FROM DriverType WHERE PackageFolder = @f",
tx, ("@f", package.Folder));
ExecuteNonQuery(conn, "DELETE FROM DriverPackage WHERE Folder = @f",
tx, ("@f", package.Folder));
var assemblies = package.Assemblies ?? new DriverAssemblyInfo[0];
ExecuteNonQuery(conn,
"INSERT INTO DriverPackage(Folder, Directory, AssemblyCount, ScanTime) VALUES(@f, @d, @c, @t)",
tx,
("@f", package.Folder),
("@d", package.Directory ?? string.Empty),
("@c", assemblies.Length.ToString()),
("@t", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
int typeCount = 0;
foreach (var asm in assemblies)
{
foreach (var type in asm.Types ?? new DriverTypeInfo[0])
{
ExecuteNonQuery(conn,
@"INSERT OR REPLACE INTO DriverType(PackageFolder, AssemblyFile, FullName, DriverType, Brand)
VALUES(@p, @a, @n, @t, @b)",
tx,
("@p", package.Folder),
("@a", asm.FileName ?? string.Empty),
("@n", type.FullName ?? string.Empty),
("@t", type.DriverType ?? string.Empty),
("@b", type.Brand ?? string.Empty));
typeCount++;
}
}
tx.Commit();
log?.Invoke($"[驱动库] 已保存 {package.Folder}({assemblies.Length} 个 dll,{typeCount} 个驱动类型)");
}
}
}
catch (Exception ex)
{
log?.Invoke($"[驱动库] 保存 {package.Folder} 失败: {ex.Message}");
}
}
/// 删除一个驱动包(及其全部驱动类型)的记录。
public void RemovePackage(string folder, Action log = null)
{
if (string.IsNullOrEmpty(folder) || !EnsureReady(log))
{
return;
}
try
{
lock (_sync)
{
using (var conn = Open())
using (var tx = conn.BeginTransaction())
{
ExecuteNonQuery(conn, "DELETE FROM DriverType WHERE PackageFolder = @f", tx, ("@f", folder));
ExecuteNonQuery(conn, "DELETE FROM DriverPackage WHERE Folder = @f", tx, ("@f", folder));
tx.Commit();
}
}
log?.Invoke($"[驱动库] 已移除 {folder} 的记录");
}
catch (Exception ex)
{
log?.Invoke($"[驱动库] 移除 {folder} 失败: {ex.Message}");
}
}
/// 读取库中全部驱动类型记录(供界面/查询使用)。
public IReadOnlyList LoadDriverTypes(Action log = null)
{
var result = new List();
if (!EnsureReady(log))
{
return result;
}
try
{
lock (_sync)
{
using (var conn = Open())
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT PackageFolder, AssemblyFile, FullName, DriverType, Brand FROM DriverType ORDER BY DriverType, Brand, FullName";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
result.Add(new DriverTypeInfo
{
FullName = GetString(reader, "FullName"),
DriverType = GetString(reader, "DriverType"),
Brand = GetString(reader, "Brand")
});
}
}
}
}
}
catch (Exception ex)
{
log?.Invoke($"[驱动库] 读取驱动类型失败: {ex.Message}");
}
return result;
}
private static void ExecuteNonQuery(SQLiteConnection conn, string sql, SQLiteTransaction tx,
params (string Name, string Value)[] parameters)
{
using (var cmd = conn.CreateCommand())
{
cmd.Transaction = tx;
cmd.CommandText = sql;
foreach (var (name, value) in parameters)
{
cmd.Parameters.AddWithValue(name, value);
}
cmd.ExecuteNonQuery();
}
}
private static string GetString(SQLiteDataReader reader, string column)
{
var value = reader[column];
return value == DBNull.Value ? string.Empty : value.ToString();
}
}
}