2025-09-05 19:46:30 +08:00
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2025-11-13 11:16:31 +08:00
|
|
|
using System.Reflection;
|
2025-09-05 19:46:30 +08:00
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
|
|
|
|
|
namespace AlicizaX.UI.Runtime
|
|
|
|
|
{
|
|
|
|
|
public static class UIResRegistry
|
|
|
|
|
{
|
|
|
|
|
public readonly struct UIResInfo
|
|
|
|
|
{
|
|
|
|
|
public readonly string Location;
|
|
|
|
|
public readonly EUIResLoadType LoadType;
|
|
|
|
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public UIResInfo(string location, EUIResLoadType loadType)
|
|
|
|
|
{
|
|
|
|
|
Location = location;
|
|
|
|
|
LoadType = loadType;
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-04-23 20:19:46 +08:00
|
|
|
|
|
|
|
|
private static readonly Dictionary<RuntimeTypeHandle, UIResInfo> _typeHandleMap = new();
|
|
|
|
|
|
2025-09-05 19:46:30 +08:00
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
|
|
public static void Register(Type holderType, string location, EUIResLoadType loadType)
|
|
|
|
|
{
|
2026-04-23 20:19:46 +08:00
|
|
|
RuntimeTypeHandle handle = holderType.TypeHandle;
|
2025-09-05 19:46:30 +08:00
|
|
|
_typeHandleMap[handle] = new UIResInfo(location, loadType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static bool TryGet(RuntimeTypeHandle handle, out UIResInfo info)
|
2025-11-13 11:16:31 +08:00
|
|
|
{
|
|
|
|
|
if (_typeHandleMap.TryGetValue(handle, out info))
|
2026-04-23 20:19:46 +08:00
|
|
|
{
|
2025-11-13 11:16:31 +08:00
|
|
|
return true;
|
2026-04-23 20:19:46 +08:00
|
|
|
}
|
2025-11-13 11:16:31 +08:00
|
|
|
|
2026-04-23 20:19:46 +08:00
|
|
|
return TryReflectAndRegister(Type.GetTypeFromHandle(handle), out info);
|
2025-11-13 11:16:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
|
|
|
|
private static bool TryReflectAndRegister(Type holderType, out UIResInfo info)
|
|
|
|
|
{
|
2026-04-23 20:19:46 +08:00
|
|
|
if (holderType == null)
|
|
|
|
|
{
|
|
|
|
|
info = default;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-12-24 20:44:36 +08:00
|
|
|
return TryReflectAndRegisterInternal(holderType, out info);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
|
|
|
|
private static bool TryReflectAndRegisterInternal(Type holderType, out UIResInfo info)
|
|
|
|
|
{
|
|
|
|
|
try
|
2025-11-13 11:16:31 +08:00
|
|
|
{
|
2026-04-23 20:19:46 +08:00
|
|
|
IList<CustomAttributeData> attributes = CustomAttributeData.GetCustomAttributes(holderType);
|
|
|
|
|
for (int i = 0; i < attributes.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
CustomAttributeData attribute = attributes[i];
|
|
|
|
|
if (attribute.AttributeType.Name != nameof(UIResAttribute))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2025-12-24 20:44:36 +08:00
|
|
|
|
2026-04-23 20:19:46 +08:00
|
|
|
IList<CustomAttributeTypedArgument> args = attribute.ConstructorArguments;
|
|
|
|
|
string resLocation = args.Count > 0 ? (string)(args[0].Value ?? string.Empty) : string.Empty;
|
|
|
|
|
EUIResLoadType resLoadType = args.Count > 1
|
|
|
|
|
? (EUIResLoadType)(args[1].Value ?? EUIResLoadType.AssetBundle)
|
|
|
|
|
: EUIResLoadType.AssetBundle;
|
2025-12-24 20:44:36 +08:00
|
|
|
|
|
|
|
|
Register(holderType, resLocation, resLoadType);
|
|
|
|
|
info = _typeHandleMap[holderType.TypeHandle];
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
Log.Error($"[UI] Failed to register UI resource for {holderType.FullName}: {ex.Message}");
|
2025-11-13 11:16:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
info = default;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2025-09-05 19:46:30 +08:00
|
|
|
}
|
|
|
|
|
}
|