From 87042fb8223a9d8dac9ca4fc80a19a5c128cd916 Mon Sep 17 00:00:00 2001 From: GwWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Thu, 18 Dec 2025 21:19:14 +0800 Subject: [PATCH] =?UTF-8?q?feat(core):=20=E9=87=8D=E6=9E=84=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E5=B7=A5=E5=8E=82=E7=B3=BB=E7=BB=9F=E4=BB=A5=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E9=94=AE=E6=8E=A7=E8=B5=84=E6=BA=90=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=E4=B8=8E=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入基于键的资源工厂注册机制,替换原有的类型唯一注册方式 - 更新资源工厂接口,新增 GetFactory 方法支持键名参数 - 修改内部注册表结构,使用 (Type, string) 元组作为工厂字典键 - 在注册场景和资源时传入键名,确保资源可按名称区分 - 增强资源工厂条目信息,添加 ResourceType 和 Key 属性 - 完善工厂解析逻辑,通过类型和键双重条件匹配目标工厂 - 添加对空键值的校验,防止无效键导致运行时错误 - 优化预加载流程,仅执行明确标记为预加载的资源工厂 --- .../system/AbstractResourceFactorySystem.cs | 21 ++++-- .../system/IResourceFactorySystem.cs | 14 +++- .../system/ResourceFactory.cs | 66 +++++++++++++------ 3 files changed, 76 insertions(+), 25 deletions(-) diff --git a/GFramework.Core.Godot/system/AbstractResourceFactorySystem.cs b/GFramework.Core.Godot/system/AbstractResourceFactorySystem.cs index 9dcd006..449baa1 100644 --- a/GFramework.Core.Godot/system/AbstractResourceFactorySystem.cs +++ b/GFramework.Core.Godot/system/AbstractResourceFactorySystem.cs @@ -35,19 +35,30 @@ public abstract class AbstractResourceFactorySystem : AbstractSystem, IResourceF _registry.PreloadAll(); }); } - /// /// 注册系统所需的各种资源类型。由子类实现具体注册逻辑。 /// protected abstract void RegisterResources(); + /// - /// 获取指定类型的资源工厂函数。 + /// 根据指定的键获取资源工厂函数。 /// - /// 要获取工厂的资源类型 + /// 资源类型 + /// 资源键 /// 返回创建指定类型资源的工厂函数 - public Func Get() => _registry!.Resolve(); + public Func GetFactory(string key)=>_registry!.ResolveFactory(key); + /// + /// 根据资产目录映射信息获取资源工厂函数。 + /// + /// 资源类型 + /// 资产目录映射信息 + /// 返回创建指定类型资源的工厂函数 + public Func GetFactory(AssetCatalog.AssetCatalogMapping mapping) => _registry!.ResolveFactory(mapping.Key); + + + #region Register Helpers(声明式) /// @@ -65,6 +76,7 @@ public abstract class AbstractResourceFactorySystem : AbstractSystem, IResourceF var id = _assetCatalogSystem!.GetScene(sceneKey); _registry!.Register( + sceneKey, _resourceLoadSystem!.GetOrRegisterSceneFactory(id), preload ); @@ -87,6 +99,7 @@ public abstract class AbstractResourceFactorySystem : AbstractSystem, IResourceF var id = _assetCatalogSystem!.GetResource(resourceKey); _registry!.Register( + resourceKey, _resourceLoadSystem!.GetOrRegisterResourceFactory(id, duplicate), preload ); diff --git a/GFramework.Core.Godot/system/IResourceFactorySystem.cs b/GFramework.Core.Godot/system/IResourceFactorySystem.cs index eb84e49..4fec531 100644 --- a/GFramework.Core.Godot/system/IResourceFactorySystem.cs +++ b/GFramework.Core.Godot/system/IResourceFactorySystem.cs @@ -8,9 +8,19 @@ namespace GFramework.Core.Godot.system; public interface IResourceFactorySystem : ISystem { /// - /// 获取指定类型T的资源创建函数 + /// 根据指定键名获取指定类型T的资源创建函数 /// /// 要获取创建函数的资源类型 + /// 用于标识资源的键名 /// 返回一个创建T类型实例的函数委托 - Func Get(); + Func GetFactory(string key); + + /// + /// 根据资产目录映射获取指定类型T的资源创建函数 + /// + /// 要获取创建函数的资源类型 + /// 资产目录映射信息 + /// 返回一个创建T类型实例的函数委托 + Func GetFactory(AssetCatalog.AssetCatalogMapping mapping); } + diff --git a/GFramework.Core.Godot/system/ResourceFactory.cs b/GFramework.Core.Godot/system/ResourceFactory.cs index fd680fb..dfb2de6 100644 --- a/GFramework.Core.Godot/system/ResourceFactory.cs +++ b/GFramework.Core.Godot/system/ResourceFactory.cs @@ -19,13 +19,24 @@ public static class ResourceFactory /// 执行与该条目关联的工厂方法 /// void ExecuteFactory(); + + /// + /// 获取资源类型 + /// + Type ResourceType { get; } + + /// + /// 获取资源键值 + /// + string Key { get; } } + /// /// 表示一个具体的资源工厂条目,实现 IPreloadableEntry 接口 /// /// 资源类型 - private sealed class Entry(Func factory, bool preload) : IPreloadableEntry + private sealed class Entry(string key, Func factory, bool preload) : IPreloadableEntry { /// /// 获取用于创建资源的工厂函数 @@ -41,8 +52,19 @@ public static class ResourceFactory /// 执行工厂函数以创建资源实例 /// public void ExecuteFactory() => Factory(); + + /// + /// 获取资源的类型 + /// + public Type ResourceType => typeof(T); + + /// + /// 获取资源的键值 + /// + public string Key { get; } = key; } + /// /// 工厂注册表,管理所有已注册的资源工厂 /// @@ -51,50 +73,56 @@ public static class ResourceFactory /// /// 存储所有已注册的工厂函数,键为资源类型,值为对应的工厂条目对象 /// - private readonly Dictionary _factories = new(); + private readonly Dictionary<(Type type, string key), IPreloadableEntry> _factories = new(); /// /// 注册指定类型的资源工厂 /// /// 要注册的资源类型 + /// 键 /// 创建该类型资源的工厂函数 /// 是否需要预加载该资源,默认为false - public void Register(Func factory, bool preload = false) + public void Register(string key, Func factory, bool preload = false) { - _factories[typeof(T)] = new Entry(factory, preload); + if (string.IsNullOrWhiteSpace(key)) + throw new ArgumentException("Resource key cannot be null or empty.", nameof(key)); + + var dictKey = (typeof(T), key); + + _factories[dictKey] = new Entry(key, factory, preload); } /// /// 解析并获取指定类型的工厂函数 /// /// 要获取工厂函数的资源类型 + /// 资源键 /// 指定类型的工厂函数 /// 当指定类型的工厂未注册时抛出异常 - public Func Resolve() + public Func ResolveFactory(string key) { - // 尝试从字典中查找对应类型的工厂条目 - if (_factories.TryGetValue(typeof(T), out var obj) - && obj is Entry entry) - return entry.Factory; + var dictKey = (typeof(T), key); - // 若未找到则抛出异常 - throw new InvalidOperationException($"Factory not registered: {typeof(T).Name}"); + if (_factories.TryGetValue(dictKey, out var entry) + && entry is Entry typed) + { + return typed.Factory; + } + + throw new InvalidOperationException( + $"Factory not registered: {typeof(T).Name} with key '{key}'"); } - + /// /// 预加载所有标记为需要预加载的资源 /// public void PreloadAll() { // 遍历所有已注册的工厂 - foreach (var entry in _factories.Values) + foreach (var entry in _factories.Values.Where(entry => entry.Preload)) { - // 检查当前条目是否支持预加载且被标记为需预加载 - if (entry is IPreloadableEntry preloadable && preloadable.Preload) - { - // 执行其工厂方法进行预加载 - preloadable.ExecuteFactory(); - } + // 执行其工厂方法进行预加载 + entry.ExecuteFactory(); } } }