using System.Reflection; using Foxel.Services.Attributes; using Microsoft.EntityFrameworkCore; // For IDbContextFactory using System.Text.Json; // For JsonSerializer using Foxel.Services.Storage.Providers; // For specific config classes namespace Foxel.Services.Storage; /// /// 统一的存储服务实现 /// public class StorageService : IStorageService { private readonly IServiceProvider _serviceProvider; private readonly ILogger _logger; private readonly Dictionary _storageProviders = new(); private readonly IDbContextFactory _contextFactory; public StorageService( IServiceProvider serviceProvider, ILogger logger, IDbContextFactory contextFactory) { _serviceProvider = serviceProvider; _logger = logger; _contextFactory = contextFactory; RegisterStorageProviders(); } /// /// 使用反射扫描和注册所有标记了StorageProviderAttribute的存储提供者 /// private void RegisterStorageProviders() { // 获取当前应用程序域中所有程序集 var assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (var assembly in assemblies) { try { // 扫描每个程序集中的所有类型 var types = assembly.GetTypes() .Where(type => type is { IsClass: true, IsAbstract: false } && type.GetInterfaces().Contains(typeof(IStorageProvider)) && type.GetCustomAttribute() != null); foreach (var type in types) { var attribute = type.GetCustomAttribute(); if (attribute != null) { // 注册存储提供者类型与对应的存储类型 _storageProviders[attribute.StorageType] = type; _logger.LogInformation("已注册存储提供者: {StorageType} -> {ProviderType}", attribute.StorageType, type.FullName); } } } catch (ReflectionTypeLoadException ex) // 更具体地捕获加载类型时的异常 { _logger.LogWarning(ex, "扫描程序集 {AssemblyName} 时发生类型加载错误。详细信息: {LoaderExceptions}", assembly.FullName, string.Join(", ", ex.LoaderExceptions.Select(e => e?.Message ?? "N/A"))); } catch (Exception ex) { _logger.LogWarning(ex, "扫描程序集 {AssemblyName} 时发生错误", assembly.FullName); // 继续扫描其他程序集 } } if (!_storageProviders.Any()) { _logger.LogWarning("未能注册任何存储提供者。请检查提供者是否正确标记了 [StorageProvider] 特性并且位于扫描的程序集中。"); } } /// /// 根据 StorageModeId 获取并配置提供者实例 /// private IStorageProvider GetProvider(int storageModeId) { using var context = _contextFactory.CreateDbContext(); var storageMode = context.StorageModes .AsNoTracking() .FirstOrDefault(sm => sm.Id == storageModeId); if (storageMode == null) { _logger.LogError("ID 为 {StorageModeId} 的 StorageMode 未找到。", storageModeId); throw new ArgumentException($"ID 为 {storageModeId} 的 StorageMode 未找到。"); } if (!storageMode.IsEnabled) { _logger.LogWarning("StorageMode {StorageModeId} ({StorageModeName}) 未启用。", storageModeId, storageMode.Name); throw new InvalidOperationException($"StorageMode '{storageMode.Name}' (ID: {storageModeId}) 未启用。"); } if (!_storageProviders.TryGetValue(storageMode.StorageType, out var providerType)) { _logger.LogError("未找到 StorageType {StorageType} (来自 StorageMode {StorageModeId}) 的已注册提供者。", storageMode.StorageType, storageModeId); throw new ArgumentException($"未找到 StorageType {storageMode.StorageType} 的提供者。"); } object specificConfig = DeserializeProviderConfig(storageMode.StorageType, storageMode.ConfigurationJson, storageMode.Name); try { return (IStorageProvider)ActivatorUtilities.CreateInstance(_serviceProvider, providerType, specificConfig); } catch (Exception ex) { _logger.LogError(ex, "为 StorageMode {StorageModeName} (ID: {StorageModeId}, Type: {StorageType}) 创建提供者 {ProviderType} 的实例失败。", storageMode.Name, storageModeId, storageMode.StorageType, providerType.FullName); throw new InvalidOperationException($"创建存储提供者 '{providerType.Name}' 失败: {ex.Message}", ex); } } private object DeserializeProviderConfig(StorageType storageType, string? jsonConfig, string storageModeName) { if (string.IsNullOrWhiteSpace(jsonConfig)) { _logger.LogError("StorageMode '{StorageModeName}' (Type: {StorageType}) 的 ConfigurationJson 为空或空白。", storageModeName, storageType); throw new InvalidOperationException($"StorageMode '{storageModeName}' (Type: {storageType}) 的配置 (ConfigurationJson) 为空。"); } try { switch (storageType) { case StorageType.Local: return JsonSerializer.Deserialize(jsonConfig) ?? throw new JsonException($"无法反序列化 LocalStorageConfig。JSON: {jsonConfig}"); case StorageType.Telegram: return JsonSerializer.Deserialize(jsonConfig) ?? throw new JsonException($"无法反序列化 TelegramStorageConfig。JSON: {jsonConfig}"); case StorageType.S3: return JsonSerializer.Deserialize(jsonConfig) ?? throw new JsonException($"无法反序列化 S3StorageConfig。JSON: {jsonConfig}"); case StorageType.Cos: return JsonSerializer.Deserialize(jsonConfig) ?? throw new JsonException($"无法反序列化 CosStorageConfig。JSON: {jsonConfig}"); case StorageType.WebDAV: return JsonSerializer.Deserialize(jsonConfig) ?? throw new JsonException($"无法反序列化 WebDavStorageConfig。JSON: {jsonConfig}"); default: _logger.LogError("不支持的存储类型配置反序列化: {StorageType} (来自 StorageMode '{StorageModeName}')", storageType, storageModeName); throw new NotSupportedException($"不支持 StorageType {storageType} 的配置反序列化。"); } } catch (JsonException ex) { _logger.LogError(ex, "反序列化 StorageMode '{StorageModeName}' (Type: {StorageType}) 的配置失败。JSON: {JsonConfig}", storageModeName, storageType, jsonConfig); throw new InvalidOperationException($"StorageMode '{storageModeName}' (Type: {storageType}) 的配置格式无效。", ex); } } /// /// 在指定存储模式上执行操作 /// public async Task ExecuteAsync(int storageModeId, Func> operation) { var provider = GetProvider(storageModeId); return await operation(provider); } /// /// 在指定存储模式上执行无返回值的操作 /// public async Task ExecuteAsync(int storageModeId, Func operation) { var provider = GetProvider(storageModeId); await operation(provider); } }