using System;
using System.Collections.Generic;
using System.Linq;
namespace GFramework.Game.Abstractions.assets;
///
/// 资源工厂类,用于注册和解析各种资源的创建工厂
///
public static class ResourceFactory
{
///
/// 可预加载条目接口,定义了是否需要预加载以及执行工厂的方法
///
private interface IPreloadableEntry
{
///
/// 获取一个值,表示该资源是否需要预加载
///
bool Preload { get; }
///
/// 获取资源类型
///
Type ResourceType { get; }
///
/// 获取资源键值
///
string Key { get; }
///
/// 执行与该条目关联的工厂方法
///
void ExecuteFactory();
}
///
/// 表示一个具体的资源工厂条目,实现 IPreloadableEntry 接口
///
/// 资源类型
private sealed class Entry(string key, Func factory, bool preload) : IPreloadableEntry
{
///
/// 获取用于创建资源的工厂函数
///
public Func Factory { get; } = factory;
///
/// 获取一个值,表示该资源是否需要预加载
///
public bool Preload { get; } = preload;
///
/// 执行工厂函数以创建资源实例
///
public void ExecuteFactory()
{
Factory();
}
///
/// 获取资源的类型
///
public Type ResourceType => typeof(T);
///
/// 获取资源的键值
///
public string Key { get; } = key;
}
///
/// 工厂注册表,管理所有已注册的资源工厂
///
public sealed class Registry
{
///
/// 存储所有已注册的工厂函数,键为资源类型,值为对应的工厂条目对象
///
private readonly Dictionary<(Type type, string key), IPreloadableEntry> _factories = new();
///
/// 注册指定类型的资源工厂
///
/// 要注册的资源类型
/// 键
/// 创建该类型资源的工厂函数
/// 是否需要预加载该资源,默认为false
public void Register(string key, Func factory, bool preload = false)
{
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 ResolveFactory(string key)
{
var dictKey = (typeof(T), key);
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.Where(entry => entry.Preload))
// 执行其工厂方法进行预加载
entry.ExecuteFactory();
}
}
}