using System.Collections.Concurrent; namespace GFramework.Core.resource; /// /// 资源缓存条目 /// internal sealed class ResourceCacheEntry(object resource, Type resourceType) { public object Resource { get; } = resource ?? throw new ArgumentNullException(nameof(resource)); public Type ResourceType { get; } = resourceType ?? throw new ArgumentNullException(nameof(resourceType)); public int ReferenceCount { get; set; } public DateTime LastAccessTime { get; set; } = DateTime.UtcNow; } /// /// 资源缓存系统,管理已加载资源的缓存和引用计数 /// 线程安全:所有公共方法都是线程安全的 /// internal sealed class ResourceCache { /// /// Path 参数验证错误消息常量 /// private const string PathCannotBeNullOrEmptyMessage = "Path cannot be null or whitespace."; private readonly ConcurrentDictionary _cache = new(); private readonly object _lock = new(); /// /// 获取已缓存资源的数量 /// public int Count => _cache.Count; /// /// 添加资源到缓存 /// /// 资源类型 /// 资源路径 /// 资源实例 /// 如果成功添加返回 true,如果已存在返回 false public bool Add(string path, T resource) where T : class { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(PathCannotBeNullOrEmptyMessage, nameof(path)); ArgumentNullException.ThrowIfNull(resource); var entry = new ResourceCacheEntry(resource, typeof(T)); return _cache.TryAdd(path, entry); } /// /// 从缓存中获取资源 /// /// 资源类型 /// 资源路径 /// 资源实例,如果不存在或类型不匹配返回 null public T? Get(string path) where T : class { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(PathCannotBeNullOrEmptyMessage, nameof(path)); if (_cache.TryGetValue(path, out var entry)) { lock (_lock) { entry.LastAccessTime = DateTime.UtcNow; } if (entry.Resource is T typedResource) { return typedResource; } } return null; } /// /// 检查资源是否在缓存中 /// /// 资源路径 /// 如果存在返回 true,否则返回 false public bool Contains(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(PathCannotBeNullOrEmptyMessage, nameof(path)); return _cache.ContainsKey(path); } /// /// 从缓存中移除资源 /// /// 资源路径 /// 如果成功移除返回 true,否则返回 false public bool Remove(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(PathCannotBeNullOrEmptyMessage, nameof(path)); return _cache.TryRemove(path, out _); } /// /// 清空所有缓存 /// public void Clear() { _cache.Clear(); } /// /// 增加资源的引用计数 /// /// 资源路径 /// 如果成功增加返回 true,如果资源不存在返回 false public bool AddReference(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(PathCannotBeNullOrEmptyMessage, nameof(path)); if (_cache.TryGetValue(path, out var entry)) { lock (_lock) { entry.ReferenceCount++; entry.LastAccessTime = DateTime.UtcNow; } return true; } return false; } /// /// 减少资源的引用计数 /// /// 资源路径 /// 减少后的引用计数,如果资源不存在返回 -1 public int RemoveReference(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(PathCannotBeNullOrEmptyMessage, nameof(path)); if (_cache.TryGetValue(path, out var entry)) { lock (_lock) { entry.ReferenceCount--; return entry.ReferenceCount; } } return -1; } /// /// 获取资源的引用计数 /// /// 资源路径 /// 引用计数,如果资源不存在返回 -1 public int GetReferenceCount(string path) { if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException(PathCannotBeNullOrEmptyMessage, nameof(path)); if (_cache.TryGetValue(path, out var entry)) { lock (_lock) { return entry.ReferenceCount; } } return -1; } /// /// 获取所有已缓存资源的路径 /// /// 资源路径集合 public IEnumerable GetAllPaths() { return _cache.Keys.ToList(); } /// /// 获取所有引用计数为 0 的资源路径 /// /// 资源路径集合 public IEnumerable GetUnreferencedPaths() { var unreferencedPaths = new List(); foreach (var kvp in _cache) { lock (_lock) { if (kvp.Value.ReferenceCount <= 0) { unreferencedPaths.Add(kvp.Key); } } } return unreferencedPaths; } }