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