com.alicizax.unity.framework/Runtime/UI/Constant/UIMetaRegistry.cs

141 lines
5.2 KiB
C#
Raw Normal View History

2025-09-05 19:46:30 +08:00
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
2025-11-13 11:16:31 +08:00
using System.Linq;
using System.Reflection;
2025-09-05 19:46:30 +08:00
using System.Runtime.CompilerServices;
2025-12-24 20:44:36 +08:00
using UnityEngine;
2025-11-13 17:46:20 +08:00
using UnityEngine.PlayerLoop;
2025-09-05 19:46:30 +08:00
namespace AlicizaX.UI.Runtime
{
public static class UIMetaRegistry
{
public readonly struct UIMetaInfo
{
public readonly RuntimeTypeHandle RuntimeTypeHandle;
public readonly RuntimeTypeHandle HolderRuntimeTypeHandle;
public readonly int UILayer;
public readonly bool FullScreen;
public readonly int CacheTime;
2025-11-13 17:46:20 +08:00
public readonly bool NeedUpdate;
2025-09-05 19:46:30 +08:00
2025-11-13 17:46:20 +08:00
public UIMetaInfo(RuntimeTypeHandle runtimeTypeHandle, RuntimeTypeHandle holderRuntimeTypeHandle, UILayer windowLayer, bool fullScreen, int cacheTime, bool needUpdate)
2025-09-05 19:46:30 +08:00
{
RuntimeTypeHandle = runtimeTypeHandle;
HolderRuntimeTypeHandle = holderRuntimeTypeHandle;
UILayer = (int)windowLayer;
FullScreen = fullScreen;
CacheTime = cacheTime;
2025-11-13 17:46:20 +08:00
NeedUpdate = needUpdate;
2025-09-05 19:46:30 +08:00
}
}
private static readonly Dictionary<RuntimeTypeHandle, UIMetaInfo> _typeHandleMap = new();
private static readonly Dictionary<string, RuntimeTypeHandle> _stringHandleMap = new();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2025-11-13 17:46:20 +08:00
public static void Register(Type uiType, Type holderType, UILayer layer = UILayer.UI, bool fullScreen = false, int cacheTime = 0, bool needUpdate = false)
2025-09-05 19:46:30 +08:00
{
var holderHandle = holderType.TypeHandle;
var uiHandle = uiType.TypeHandle;
2025-11-13 17:46:20 +08:00
_typeHandleMap[uiHandle] = new UIMetaInfo(uiHandle, holderHandle, layer, fullScreen, cacheTime, needUpdate);
2025-09-05 19:46:30 +08:00
_stringHandleMap[uiType.Name] = uiHandle;
}
2025-11-13 11:16:31 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2025-09-05 19:46:30 +08:00
public static bool TryGet(RuntimeTypeHandle handle, out UIMetaInfo info)
{
2025-11-13 11:16:31 +08:00
if (_typeHandleMap.TryGetValue(handle, out info))
return true;
var t = Type.GetTypeFromHandle(handle);
if (TryReflectAndRegister(t, out info))
return true;
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryGet(string typeName, out UIMetaInfo info)
{
if (_stringHandleMap.TryGetValue(typeName, out var handle))
return TryGet(handle, out info);
var type = AlicizaX.Utility.Assembly.GetType(typeName);
if (type != null && TryReflectAndRegister(type, out info))
return true;
info = default;
return false;
2025-09-05 19:46:30 +08:00
}
2025-11-13 11:16:31 +08:00
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool TryReflectAndRegister(Type uiType, out UIMetaInfo info)
2025-09-05 19:46:30 +08:00
{
2025-11-13 11:16:31 +08:00
Log.Warning($"[UI] UI未注册[{uiType.FullName}] 反射进行缓存");
2025-12-24 20:44:36 +08:00
return TryReflectAndRegisterInternal(uiType, out info);
}
/// <summary>
/// Internal method to reflect and register UI type without logging.
/// Used by both runtime fallback and pre-registration.
/// </summary>
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool TryReflectAndRegisterInternal(Type uiType, out UIMetaInfo info)
{
try
2025-11-13 11:16:31 +08:00
{
2025-12-24 20:44:36 +08:00
Type baseType = uiType;
Type? holderType = null;
// Get holder type from generic arguments
var genericArgs = baseType.GetGenericArguments();
if (genericArgs.Length > 0)
{
holderType = genericArgs[0];
}
UILayer layer = UILayer.UI;
bool fullScreen = false;
int cacheTime = 0;
bool needUpdate = false;
// Read attributes
var windowAttribute = CustomAttributeData.GetCustomAttributes(uiType)
.FirstOrDefault(a => a.AttributeType.Name == nameof(WindowAttribute));
var uiUpdateAttribute = CustomAttributeData.GetCustomAttributes(uiType)
.FirstOrDefault(a => a.AttributeType.Name == nameof(UIUpdateAttribute));
if (windowAttribute != null)
{
var args = windowAttribute.ConstructorArguments;
if (args.Count > 0) layer = (UILayer)(args[0].Value ?? UILayer.UI);
if (args.Count > 1) fullScreen = (bool)(args[1].Value ?? false);
if (args.Count > 2) cacheTime = (int)(args[2].Value ?? 0);
}
needUpdate = uiUpdateAttribute != null;
if (holderType != null)
{
Register(uiType, holderType, layer, fullScreen, cacheTime, needUpdate);
info = _typeHandleMap[uiType.TypeHandle];
return true;
}
2025-11-13 11:16:31 +08:00
}
2025-12-24 20:44:36 +08:00
catch (Exception ex)
2025-09-05 19:46:30 +08:00
{
2025-12-24 20:44:36 +08:00
Log.Error($"[UI] Failed to register UI type {uiType.FullName}: {ex.Message}");
2025-09-05 19:46:30 +08:00
}
2025-11-13 11:16:31 +08:00
info = default;
return false;
2025-09-05 19:46:30 +08:00
}
}
}