using System.Collections.Concurrent; using GFramework.Core.Abstractions.Logging; using GFramework.Core.Abstractions.Resource; using GFramework.Core.Logging; namespace GFramework.Core.Resource; /// /// 资源管理器实现,提供资源加载、缓存和卸载功能 /// 线程安全:所有公共方法都是线程安全的 /// public class ResourceManager : IResourceManager { /// /// Path 参数验证错误消息常量 /// private const string PathCannotBeNullOrEmptyMessage = "Path cannot be null or whitespace."; private readonly ResourceCache _cache = new(); private readonly ConcurrentDictionary _loaders = new(); private readonly object _loadLock = new(); private readonly ILogger _logger = LoggerFactoryResolver.Provider.CreateLogger(nameof(ResourceManager)); private IResourceReleaseStrategy _releaseStrategy; /// /// 创建资源管理器 /// 默认使用手动释放策略 /// public ResourceManager() { _releaseStrategy = new ManualReleaseStrategy(); } /// /// 获取已加载资源的数量 /// public int LoadedResourceCount => _cache.Count; /// /// 同步加载资源 /// public T? Load(string path) where T : class { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(PathCannotBeNullOrEmptyMessage, nameof(path)); // 检查缓存 var cached = _cache.Get(path); if (cached != null) { return cached; } // 加载资源 lock (_loadLock) { // 双重检查 cached = _cache.Get(path); if (cached != null) { return cached; } var loader = GetLoader(); if (loader == null) { throw new InvalidOperationException($"No loader registered for type {typeof(T).Name}"); } try { var resource = loader.Load(path); _cache.Add(path, resource); return resource; } catch (Exception ex) { _logger.Error($"Failed to load resource '{path}'", ex); return null; } } } /// /// 异步加载资源 /// public async Task LoadAsync(string path) where T : class { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(PathCannotBeNullOrEmptyMessage, nameof(path)); // 检查缓存 var cached = _cache.Get(path); if (cached != null) { return cached; } var loader = GetLoader(); if (loader == null) { throw new InvalidOperationException($"No loader registered for type {typeof(T).Name}"); } try { var resource = await loader.LoadAsync(path); lock (_loadLock) { // 双重检查 cached = _cache.Get(path); if (cached != null) { // 已经被其他线程加载了,卸载当前加载的资源 loader.Unload(resource); return cached; } _cache.Add(path, resource); } return resource; } catch (Exception ex) { _logger.Error($"Failed to load resource '{path}'", ex); return null; } } /// /// 获取资源句柄 /// public IResourceHandle? GetHandle(string path) where T : class { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(PathCannotBeNullOrEmptyMessage, nameof(path)); var resource = _cache.Get(path); if (resource == null) return null; _cache.AddReference(path); return new ResourceHandle(resource, path, HandleDispose); } /// /// 卸载指定路径的资源 /// public bool Unload(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(PathCannotBeNullOrEmptyMessage, nameof(path)); lock (_loadLock) { var resource = _cache.Get(path); if (resource == null) return false; // 检查引用计数 var refCount = _cache.GetReferenceCount(path); if (refCount > 0) { _logger.Error($"Cannot unload resource '{path}' with {refCount} active references"); return false; } // 卸载资源 UnloadResource(resource); // 从缓存中移除 return _cache.Remove(path); } } /// /// 卸载所有资源 /// public void UnloadAll() { lock (_loadLock) { var paths = _cache.GetAllPaths().ToList(); foreach (var path in paths) { var resource = _cache.Get(path); if (resource != null) { UnloadResource(resource); } } _cache.Clear(); } } /// /// 检查资源是否已加载 /// public bool IsLoaded(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(PathCannotBeNullOrEmptyMessage, nameof(path)); return _cache.Contains(path); } /// /// 注册资源加载器 /// public void RegisterLoader(IResourceLoader loader) where T : class { if (loader == null) throw new ArgumentNullException(nameof(loader)); _loaders[typeof(T)] = loader; } /// /// 取消注册资源加载器 /// public void UnregisterLoader() where T : class { _loaders.TryRemove(typeof(T), out _); } /// /// 预加载资源 /// public async Task PreloadAsync(string path) where T : class { await LoadAsync(path); } /// /// 获取所有已加载资源的路径 /// public IEnumerable GetLoadedResourcePaths() { return _cache.GetAllPaths(); } /// /// 设置资源释放策略 /// /// 资源释放策略 public void SetReleaseStrategy(IResourceReleaseStrategy strategy) { _releaseStrategy = strategy ?? throw new ArgumentNullException(nameof(strategy)); } /// /// 获取指定类型的资源加载器 /// private IResourceLoader? GetLoader() where T : class { if (_loaders.TryGetValue(typeof(T), out var loader)) { return loader as IResourceLoader; } return null; } /// /// 卸载资源实例 /// private void UnloadResource(object resource) { var resourceType = resource.GetType(); if (_loaders.TryGetValue(resourceType, out var loaderObj)) { try { var unloadMethod = loaderObj.GetType().GetMethod("Unload"); unloadMethod?.Invoke(loaderObj, new[] { resource }); } catch (Exception ex) { _logger.Error("Error unloading resource", ex); } } // 如果资源实现了 IDisposable,调用 Dispose if (resource is IDisposable disposable) { try { disposable.Dispose(); } catch (Exception ex) { _logger.Error("Error disposing resource", ex); } } } /// /// 句柄释放时的回调 /// private void HandleDispose(string path) { var refCount = _cache.RemoveReference(path); // 使用策略模式判断是否应该释放资源 if (_releaseStrategy.ShouldRelease(path, refCount)) { lock (_loadLock) { // 双重检查引用计数,避免竞态条件 var currentRefCount = _cache.GetReferenceCount(path); if (currentRefCount <= 0) { var resource = _cache.Get(path); if (resource != null) { UnloadResource(resource); _cache.Remove(path); } } } } } }