com.alicizax.unity.framework/Runtime/UI/Constant/UIMetaRegistry.cs
陈思海 cd5de2c374 优化UIService模块
优化UI模块更多细节容错处理 优化UI模块内存泄露问题 优化性能
2026-04-23 20:19:46 +08:00

164 lines
5.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
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;
public readonly bool NeedUpdate;
public UIMetaInfo(RuntimeTypeHandle runtimeTypeHandle, RuntimeTypeHandle holderRuntimeTypeHandle, UILayer windowLayer, bool fullScreen, int cacheTime, bool needUpdate)
{
RuntimeTypeHandle = runtimeTypeHandle;
HolderRuntimeTypeHandle = holderRuntimeTypeHandle;
UILayer = (int)windowLayer;
FullScreen = fullScreen;
CacheTime = cacheTime;
NeedUpdate = needUpdate;
}
}
private static readonly Dictionary<RuntimeTypeHandle, UIMetaInfo> _typeHandleMap = new();
private static readonly Dictionary<string, RuntimeTypeHandle> _stringHandleMap = new();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Register(Type uiType, Type holderType, UILayer layer = UILayer.UI, bool fullScreen = false, int cacheTime = 0, bool needUpdate = false)
{
RuntimeTypeHandle holderHandle = holderType.TypeHandle;
RuntimeTypeHandle uiHandle = uiType.TypeHandle;
_typeHandleMap[uiHandle] = new UIMetaInfo(uiHandle, holderHandle, layer, fullScreen, cacheTime, needUpdate);
_stringHandleMap[uiType.Name] = uiHandle;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryGet(RuntimeTypeHandle handle, out UIMetaInfo info)
{
if (_typeHandleMap.TryGetValue(handle, out info))
{
return true;
}
return TryReflectAndRegister(Type.GetTypeFromHandle(handle), out info);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryGet(string typeName, out UIMetaInfo info)
{
if (_stringHandleMap.TryGetValue(typeName, out RuntimeTypeHandle handle))
{
return TryGet(handle, out info);
}
Type type = AlicizaX.Utility.Assembly.GetType(typeName);
if (type != null && TryReflectAndRegister(type, out info))
{
return true;
}
info = default;
return false;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool TryReflectAndRegister(Type uiType, out UIMetaInfo info)
{
if (uiType == null)
{
info = default;
return false;
}
Log.Warning($"[UI] UI not pre-registered: {uiType.FullName}, using reflection fallback.");
return TryReflectAndRegisterInternal(uiType, out info);
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool TryReflectAndRegisterInternal(Type uiType, out UIMetaInfo info)
{
try
{
Type holderType = ResolveHolderType(uiType);
if (holderType == null)
{
info = default;
return false;
}
UILayer layer = UILayer.UI;
bool fullScreen = false;
int cacheTime = 0;
bool needUpdate = false;
IList<CustomAttributeData> attributes = CustomAttributeData.GetCustomAttributes(uiType);
for (int i = 0; i < attributes.Count; i++)
{
CustomAttributeData attribute = attributes[i];
string attributeName = attribute.AttributeType.Name;
if (attributeName == nameof(WindowAttribute))
{
IList<CustomAttributeTypedArgument> args = attribute.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);
}
}
else if (attributeName == nameof(UIUpdateAttribute))
{
needUpdate = true;
}
}
Register(uiType, holderType, layer, fullScreen, cacheTime, needUpdate);
info = _typeHandleMap[uiType.TypeHandle];
return true;
}
catch (Exception ex)
{
Log.Error($"[UI] Failed to register UI type {uiType.FullName}: {ex.Message}");
}
info = default;
return false;
}
private static Type ResolveHolderType(Type uiType)
{
Type current = uiType;
while (current != null && current != typeof(object))
{
if (current.IsGenericType)
{
Type[] genericArgs = current.GetGenericArguments();
if (genericArgs.Length == 1 && typeof(UIHolderObjectBase).IsAssignableFrom(genericArgs[0]))
{
return genericArgs[0];
}
}
current = current.BaseType;
}
return null;
}
}
}