mirror of
https://github.com/GeWuYou/GFramework.git
synced 2026-03-23 11:14:30 +08:00
feat(core): 重构资源工厂系统以支持键控资源注册与解析
- 引入基于键的资源工厂注册机制,替换原有的类型唯一注册方式 - 更新资源工厂接口,新增 GetFactory 方法支持键名参数 - 修改内部注册表结构,使用 (Type, string) 元组作为工厂字典键 - 在注册场景和资源时传入键名,确保资源可按名称区分 - 增强资源工厂条目信息,添加 ResourceType 和 Key 属性 - 完善工厂解析逻辑,通过类型和键双重条件匹配目标工厂 - 添加对空键值的校验,防止无效键导致运行时错误 - 优化预加载流程,仅执行明确标记为预加载的资源工厂
This commit is contained in:
parent
8123683e6e
commit
24fa11cf1b
@ -35,19 +35,30 @@ public abstract class AbstractResourceFactorySystem : AbstractSystem, IResourceF
|
||||
_registry.PreloadAll();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册系统所需的各种资源类型。由子类实现具体注册逻辑。
|
||||
/// </summary>
|
||||
protected abstract void RegisterResources();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定类型的资源工厂函数。
|
||||
/// 根据指定的键获取资源工厂函数。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要获取工厂的资源类型</typeparam>
|
||||
/// <typeparam name="T">资源类型</typeparam>
|
||||
/// <param name="key">资源键</param>
|
||||
/// <returns>返回创建指定类型资源的工厂函数</returns>
|
||||
public Func<T> Get<T>() => _registry!.Resolve<T>();
|
||||
public Func<T> GetFactory<T>(string key)=>_registry!.ResolveFactory<T>(key);
|
||||
|
||||
/// <summary>
|
||||
/// 根据资产目录映射信息获取资源工厂函数。
|
||||
/// </summary>
|
||||
/// <typeparam name="T">资源类型</typeparam>
|
||||
/// <param name="mapping">资产目录映射信息</param>
|
||||
/// <returns>返回创建指定类型资源的工厂函数</returns>
|
||||
public Func<T> GetFactory<T>(AssetCatalog.AssetCatalogMapping mapping) => _registry!.ResolveFactory<T>(mapping.Key);
|
||||
|
||||
|
||||
|
||||
#region Register Helpers(声明式)
|
||||
|
||||
/// <summary>
|
||||
@ -65,6 +76,7 @@ public abstract class AbstractResourceFactorySystem : AbstractSystem, IResourceF
|
||||
var id = _assetCatalogSystem!.GetScene(sceneKey);
|
||||
|
||||
_registry!.Register(
|
||||
sceneKey,
|
||||
_resourceLoadSystem!.GetOrRegisterSceneFactory<T>(id),
|
||||
preload
|
||||
);
|
||||
@ -87,6 +99,7 @@ public abstract class AbstractResourceFactorySystem : AbstractSystem, IResourceF
|
||||
var id = _assetCatalogSystem!.GetResource(resourceKey);
|
||||
|
||||
_registry!.Register(
|
||||
resourceKey,
|
||||
_resourceLoadSystem!.GetOrRegisterResourceFactory<T>(id, duplicate),
|
||||
preload
|
||||
);
|
||||
|
||||
@ -8,9 +8,19 @@ namespace GFramework.Core.Godot.system;
|
||||
public interface IResourceFactorySystem : ISystem
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取指定类型T的资源创建函数
|
||||
/// 根据指定键名获取指定类型T的资源创建函数
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要获取创建函数的资源类型</typeparam>
|
||||
/// <param name="key">用于标识资源的键名</param>
|
||||
/// <returns>返回一个创建T类型实例的函数委托</returns>
|
||||
Func<T> Get<T>();
|
||||
Func<T> GetFactory<T>(string key);
|
||||
|
||||
/// <summary>
|
||||
/// 根据资产目录映射获取指定类型T的资源创建函数
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要获取创建函数的资源类型</typeparam>
|
||||
/// <param name="mapping">资产目录映射信息</param>
|
||||
/// <returns>返回一个创建T类型实例的函数委托</returns>
|
||||
Func<T> GetFactory<T>(AssetCatalog.AssetCatalogMapping mapping);
|
||||
}
|
||||
|
||||
|
||||
@ -19,13 +19,24 @@ public static class ResourceFactory
|
||||
/// 执行与该条目关联的工厂方法
|
||||
/// </summary>
|
||||
void ExecuteFactory();
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源类型
|
||||
/// </summary>
|
||||
Type ResourceType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源键值
|
||||
/// </summary>
|
||||
string Key { get; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 表示一个具体的资源工厂条目,实现 IPreloadableEntry 接口
|
||||
/// </summary>
|
||||
/// <typeparam name="T">资源类型</typeparam>
|
||||
private sealed class Entry<T>(Func<T> factory, bool preload) : IPreloadableEntry
|
||||
private sealed class Entry<T>(string key, Func<T> factory, bool preload) : IPreloadableEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取用于创建资源的工厂函数
|
||||
@ -41,8 +52,19 @@ public static class ResourceFactory
|
||||
/// 执行工厂函数以创建资源实例
|
||||
/// </summary>
|
||||
public void ExecuteFactory() => Factory();
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源的类型
|
||||
/// </summary>
|
||||
public Type ResourceType => typeof(T);
|
||||
|
||||
/// <summary>
|
||||
/// 获取资源的键值
|
||||
/// </summary>
|
||||
public string Key { get; } = key;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 工厂注册表,管理所有已注册的资源工厂
|
||||
/// </summary>
|
||||
@ -51,50 +73,56 @@ public static class ResourceFactory
|
||||
/// <summary>
|
||||
/// 存储所有已注册的工厂函数,键为资源类型,值为对应的工厂条目对象
|
||||
/// </summary>
|
||||
private readonly Dictionary<Type, object> _factories = new();
|
||||
private readonly Dictionary<(Type type, string key), IPreloadableEntry> _factories = new();
|
||||
|
||||
/// <summary>
|
||||
/// 注册指定类型的资源工厂
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要注册的资源类型</typeparam>
|
||||
/// <param name="key">键</param>
|
||||
/// <param name="factory">创建该类型资源的工厂函数</param>
|
||||
/// <param name="preload">是否需要预加载该资源,默认为false</param>
|
||||
public void Register<T>(Func<T> factory, bool preload = false)
|
||||
public void Register<T>(string key, Func<T> factory, bool preload = false)
|
||||
{
|
||||
_factories[typeof(T)] = new Entry<T>(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<T>(key, factory, preload);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析并获取指定类型的工厂函数
|
||||
/// </summary>
|
||||
/// <typeparam name="T">要获取工厂函数的资源类型</typeparam>
|
||||
/// <param name="key">资源键</param>
|
||||
/// <returns>指定类型的工厂函数</returns>
|
||||
/// <exception cref="InvalidOperationException">当指定类型的工厂未注册时抛出异常</exception>
|
||||
public Func<T> Resolve<T>()
|
||||
public Func<T> ResolveFactory<T>(string key)
|
||||
{
|
||||
// 尝试从字典中查找对应类型的工厂条目
|
||||
if (_factories.TryGetValue(typeof(T), out var obj)
|
||||
&& obj is Entry<T> 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<T> typed)
|
||||
{
|
||||
return typed.Factory;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(
|
||||
$"Factory not registered: {typeof(T).Name} with key '{key}'");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 预加载所有标记为需要预加载的资源
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user