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