using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; using Newtonsoft.Json; using TeamAAS.Database.Attributes; using TeamAAS.Database.Interfaces; using TeamAAS.Database.Models; namespace TeamAAS.Database { /// /// 数据库管理器。 /// 负责多数据库实例的创建、注册、移除、配置持久化以及提供者反射发现。 /// 懒汉单例模式:DatabaseManager.Instance /// public class DatabaseManager : IDatabaseManager { #region 单例 private static readonly Lazy _instance = new Lazy(() => new DatabaseManager(), isThreadSafe: true); /// /// 懒汉单例入口。首次访问时初始化,线程安全。 /// public static DatabaseManager Instance => _instance.Value; #endregion #region 字段 private readonly Dictionary _databases; private readonly object _sync = new object(); // 反射扫描的提供者缓存 private List _providers; private readonly object _providerLock = new object(); // 配置文件路径 private string _configPath; #endregion #region 构造 public DatabaseManager() { _databases = new Dictionary(); } #endregion #region 提供者发现 /// /// 获取所有可用的数据库提供者(反射扫描当前程序集及已加载程序集中的 IDatabase 实现) /// public List GetAvailableProviders() { lock (_providerLock) { if (_providers != null) return _providers.ToList(); _providers = new List(); try { // 反射扫描:收集全部 IDatabase 实现(当前程序集 + 同级目录下的 DLL) foreach (var type in ScanImplementations()) { var attr = type.GetCustomAttribute(); if (attr == null) continue; _providers.Add(new DatabaseProviderInfo { ProviderType = attr.ProviderType, DisplayName = attr.DisplayName, ImplementationType = type, RequiresServer = attr.RequiresServer, Description = attr.Description }); } } catch { /* 提供者扫描失败不抛异常 */ } return _providers.ToList(); } } /// /// 根据 providerType 创建数据库实例 /// private IDatabase CreateDatabaseInstance(DatabaseConfig config) { var providers = GetAvailableProviders(); var provider = providers.FirstOrDefault( p => string.Equals(p.ProviderType, config.ProviderType, StringComparison.OrdinalIgnoreCase)); if (provider == null) throw new InvalidOperationException($"未找到数据库提供者:{config.ProviderType}"); var instance = (IDatabase)Activator.CreateInstance(provider.ImplementationType); instance.Configure(config); return instance; } #endregion #region 反射扫描辅助 /// /// 扫描当前程序集及应用程序基目录下所有 DLL,查找实现了 TInterface 的非抽象类。 /// private static List ScanImplementations() { var result = new List(); var interfaceType = typeof(TInterface); // 1. 当前程序集 var currentAsm = Assembly.GetExecutingAssembly(); ScanAssembly(currentAsm, interfaceType, result); // 2. 应用程序基目录下的其他 DLL(支持插件扩展) try { string baseDir = AppDomain.CurrentDomain.BaseDirectory; foreach (var dll in Directory.GetFiles(baseDir, "*.dll", SearchOption.TopDirectoryOnly)) { try { var asmName = AssemblyName.GetAssemblyName(dll); if (asmName.FullName == currentAsm.FullName) continue; // 已扫描过 var asm = Assembly.Load(asmName); ScanAssembly(asm, interfaceType, result); } catch { /* 单个 DLL 加载失败跳过 */ } } } catch { /* 目录扫描失败跳过 */ } return result; } private static void ScanAssembly(Assembly asm, Type interfaceType, List result) { try { foreach (var type in asm.GetTypes()) { if (type.IsAbstract || type.IsInterface || !type.IsClass) continue; if (!interfaceType.IsAssignableFrom(type)) continue; result.Add(type); } } catch { /* 反射获取类型失败跳过 */ } } #endregion #region 数据库生命周期 public bool CreateDatabase(Guid id, DatabaseConfig config) { if (config == null) throw new ArgumentNullException(nameof(config)); if (string.IsNullOrWhiteSpace(config.ProviderType)) throw new ArgumentException("ProviderType 不能为空", nameof(config)); var database = CreateDatabaseInstance(config); IDatabase existing = null; lock (_sync) { _databases.TryGetValue(id, out existing); _databases[id] = database; } if (existing != null && !ReferenceEquals(existing, database)) { try { existing.Dispose(); } catch { } } return true; } public Task CreateDatabaseAsync(Guid id, DatabaseConfig config) { return Task.Run(() => CreateDatabase(id, config)); } public IDatabase GetDatabase(Guid id) { lock (_sync) { return _databases.TryGetValue(id, out var db) ? db : null; } } public bool TryGetDatabase(Guid id, out IDatabase database) { lock (_sync) { return _databases.TryGetValue(id, out database); } } public bool ContainsDatabase(Guid id) { lock (_sync) { return _databases.ContainsKey(id); } } public IReadOnlyCollection GetAllDatabases() { lock (_sync) { return _databases.Values.ToList().AsReadOnly(); } } public bool RemoveDatabase(Guid id) { IDatabase db = null; lock (_sync) { if (_databases.TryGetValue(id, out db)) _databases.Remove(id); } if (db != null) { try { db.Dispose(); } catch { } return true; } return false; } public Task RemoveDatabaseAsync(Guid id) { return Task.Run(() => RemoveDatabase(id)); } public void RemoveAllDatabases() { List all; lock (_sync) { all = _databases.Values.ToList(); _databases.Clear(); } foreach (var db in all) { try { db.Dispose(); } catch { } } } public (bool IsSucceed, string Message) InitializeAllDatabases(DatabaseConfig[] configs) { if (configs == null) return (true, "无配置"); var errors = new List(); var successCount = 0; foreach (var config in configs) { try { var id = config.Id == Guid.Empty ? Guid.NewGuid() : config.Id; CreateDatabase(id, config); successCount++; } catch (Exception ex) { errors.Add($"{config.Name ?? config.ProviderType}: {ex.Message}"); } } if (errors.Count == 0) return (true, $"成功初始化 {successCount} 个数据库"); return (false, $"成功 {successCount} 个,失败 {errors.Count} 个:{string.Join("; ", errors)}"); } public Task<(bool IsSucceed, string Message)> InitializeAllDatabasesAsync(DatabaseConfig[] configs) { return Task.Run(() => InitializeAllDatabases(configs)); } public IReadOnlyList GetAllDatabaseConfigs() { var result = new List(); lock (_sync) { foreach (var db in _databases.Values) { result.Add(new DatabaseConfig { Id = db.Id, Name = db.Name, ProviderType = db.ProviderType, ConnectionString = db.ConnectionString }); } } return result.AsReadOnly(); } #endregion #region 配置持久化 /// /// 保存配置到 JSON 文件 /// public bool SaveConfig(string path = null) { try { var filePath = path ?? _configPath; if (string.IsNullOrWhiteSpace(filePath)) throw new ArgumentException("配置文件路径不能为空", nameof(path)); _configPath = filePath; var configs = GetAllDatabaseConfigs(); var json = JsonConvert.SerializeObject(configs, Formatting.Indented); var dir = Path.GetDirectoryName(filePath); if (!string.IsNullOrWhiteSpace(dir) && !Directory.Exists(dir)) Directory.CreateDirectory(dir); File.WriteAllText(filePath, json); return true; } catch { return false; } } /// /// 从 JSON 文件加载配置并初始化 /// public (bool IsSucceed, string Message) LoadConfig(string path) { try { if (!File.Exists(path)) return (false, $"配置文件不存在:{path}"); _configPath = path; var json = File.ReadAllText(path); var configs = JsonConvert.DeserializeObject(json); if (configs == null || configs.Length == 0) return (true, "配置为空"); return InitializeAllDatabases(configs); } catch (Exception ex) { return (false, $"加载配置失败:{ex.Message}"); } } #endregion #region IDisposable private bool _disposed; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { RemoveAllDatabases(); } _disposed = true; } ~DatabaseManager() { Dispose(false); } #endregion } }