add MetaProxyAttribute

This commit is contained in:
Mikhail 2026-04-13 23:21:07 +08:00
parent 68d3d2bc4f
commit 371472e851
2 changed files with 103 additions and 13 deletions

View File

@ -6,7 +6,6 @@ using DCFApixels.DragonECS.Core.Internal;
using DCFApixels.DragonECS.PoolsCore; using DCFApixels.DragonECS.PoolsCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
#if DEBUG || !REFLECTION_DISABLED #if DEBUG || !REFLECTION_DISABLED
@ -51,6 +50,7 @@ namespace DCFApixels.DragonECS
private readonly int _uniqueID; private readonly int _uniqueID;
internal readonly Type _type; internal readonly Type _type;
private readonly MetaProxy _proxy;
private bool _isCustomName; private bool _isCustomName;
private bool _isCustomColor; private bool _isCustomColor;
@ -93,6 +93,7 @@ namespace DCFApixels.DragonECS
_initFlags = InitFlag.All, _initFlags = InitFlag.All,
}; };
_metaCache.Add(typeof(void).TypeHandle, NullTypeMeta); _metaCache.Add(typeof(void).TypeHandle, NullTypeMeta);
} }
public static TypeMeta Get(Type type) { return Get(type.TypeHandle); } public static TypeMeta Get(Type type) { return Get(type.TypeHandle); }
@ -108,10 +109,45 @@ namespace DCFApixels.DragonECS
return result; return result;
} }
} }
private static Type FindDeclaringType(Type targetPureType, Type currentType)
{
if (currentType == typeof(object)) { return null; }
var pure = currentType.GetPureType();
if (pure == targetPureType)
{
return currentType;
}
return FindDeclaringType(targetPureType, currentType.BaseType);
}
private TypeMeta(Type type) private TypeMeta(Type type)
{ {
_uniqueID = _increment++; _uniqueID = _increment++;
_type = type; _type = type;
_proxy = MetaProxy.EmptyProxy;
if (type.ContainsGenericParameters == false &&
type.TryGetAttribute<MetaProxyAttribute>(out var proxyAtr))
{
Type proxyType = proxyAtr.Type;
if (proxyType.ContainsGenericParameters && proxyType.IsNested)
{
var baseType = FindDeclaringType(proxyType.DeclaringType, type);
if(baseType != null)
{
var args = baseType.GetGenericArguments();
proxyType = proxyType.MakeGenericType(args);
}
}
if (proxyType.ContainsGenericParameters == false)
{
var proxy = Activator.CreateInstance(proxyType, type) as MetaProxy;
if (proxy != null)
{
_proxy = proxy;
}
}
}
} }
#endregion #endregion
@ -127,7 +163,7 @@ namespace DCFApixels.DragonECS
{ {
if (_initFlags.HasFlag(InitFlag.Name) == false) if (_initFlags.HasFlag(InitFlag.Name) == false)
{ {
(_name, _isCustomName) = MetaGenerator.GetMetaName(_type); (_name, _isCustomName) = MetaGenerator.GetMetaName(this);
_typeName = _isCustomName ? MetaGenerator.GetTypeName(_type) : _name; _typeName = _isCustomName ? MetaGenerator.GetTypeName(_type) : _name;
_initFlags |= InitFlag.Name; _initFlags |= InitFlag.Name;
} }
@ -192,7 +228,7 @@ namespace DCFApixels.DragonECS
{ {
if (_initFlags.HasFlag(InitFlag.Description) == false) if (_initFlags.HasFlag(InitFlag.Description) == false)
{ {
_description = MetaGenerator.GetDescription(_type); _description = MetaGenerator.GetDescription(this);
_initFlags |= InitFlag.Description; _initFlags |= InitFlag.Description;
} }
return _description; return _description;
@ -207,7 +243,7 @@ namespace DCFApixels.DragonECS
{ {
if (_initFlags.HasFlag(InitFlag.Group) == false) if (_initFlags.HasFlag(InitFlag.Group) == false)
{ {
_group = MetaGenerator.GetGroup(_type); _group = MetaGenerator.GetGroup(this);
_initFlags |= InitFlag.Group; _initFlags |= InitFlag.Group;
} }
return _group; return _group;
@ -220,7 +256,7 @@ namespace DCFApixels.DragonECS
{ {
if (_initFlags.HasFlag(InitFlag.Tags) == false) if (_initFlags.HasFlag(InitFlag.Tags) == false)
{ {
_tags = MetaGenerator.GetTags(_type); _tags = MetaGenerator.GetTags(this);
_initFlags |= InitFlag.Tags; _initFlags |= InitFlag.Tags;
_isHidden = _tags.Contains(MetaTags.HIDDEN); _isHidden = _tags.Contains(MetaTags.HIDDEN);
_isObsolete = _tags.Contains(MetaTags.OBSOLETE); _isObsolete = _tags.Contains(MetaTags.OBSOLETE);
@ -480,9 +516,14 @@ namespace DCFApixels.DragonECS
{ {
return EcsDebugUtility.GetGenericTypeName(type, GENERIC_NAME_DEPTH); return EcsDebugUtility.GetGenericTypeName(type, GENERIC_NAME_DEPTH);
} }
public static (string, bool) GetMetaName(Type type) public static (string, bool) GetMetaName(TypeMeta meta)
{ {
#if DEBUG || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает #if DEBUG || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает
if (meta._proxy.Name != null)
{
return (meta._proxy.Name, true);
}
var type = meta.Type;
bool isCustom = type.TryGetAttribute(out MetaNameAttribute atr) && string.IsNullOrEmpty(atr.name) == false; bool isCustom = type.TryGetAttribute(out MetaNameAttribute atr) && string.IsNullOrEmpty(atr.name) == false;
if (isCustom) if (isCustom)
{ {
@ -524,6 +565,10 @@ namespace DCFApixels.DragonECS
public static (MetaColor, bool) GetColor(TypeMeta meta) public static (MetaColor, bool) GetColor(TypeMeta meta)
{ {
#if DEBUG || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает #if DEBUG || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает
if (meta._proxy.Color != null)
{
return (meta._proxy.Color.Value, true);
}
bool isCustom = meta.Type.TryGetAttribute(out MetaColorAttribute atr); bool isCustom = meta.Type.TryGetAttribute(out MetaColorAttribute atr);
return (isCustom ? atr.color : AutoColor(meta), isCustom); return (isCustom ? atr.color : AutoColor(meta), isCustom);
#else #else
@ -534,16 +579,20 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region GetGroup #region GetGroup
public static MetaGroup GetGroup(Type type) public static MetaGroup GetGroup(TypeMeta meta)
{ {
#if DEBUG || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает #if DEBUG || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает
if (type.TryGetAttribute(out MetaGroupAttribute atr)) if (meta._proxy.Group != null)
{
return meta._proxy.Group;
}
if (meta.Type.TryGetAttribute(out MetaGroupAttribute atr))
{ {
return MetaGroup.FromName(atr.Name); return MetaGroup.FromName(atr.Name);
} }
else else
{ {
return MetaGroup.FromNameSpace(type); return MetaGroup.FromNameSpace(meta.Type);
} }
#else #else
EcsDebug.PrintWarning($"Reflection is not available, the {nameof(MetaGenerator)}.{nameof(GetGroup)} method does not work."); EcsDebug.PrintWarning($"Reflection is not available, the {nameof(MetaGenerator)}.{nameof(GetGroup)} method does not work.");
@ -553,10 +602,14 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region GetDescription #region GetDescription
public static MetaDescription GetDescription(Type type) public static MetaDescription GetDescription(TypeMeta meta)
{ {
#if DEBUG || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает #if DEBUG || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает
bool isCustom = type.TryGetAttribute(out MetaDescriptionAttribute atr); if (meta._proxy.Description != null)
{
return meta._proxy.Description;
}
bool isCustom = meta.Type.TryGetAttribute(out MetaDescriptionAttribute atr);
return isCustom ? atr.Data : MetaDescription.Empty; return isCustom ? atr.Data : MetaDescription.Empty;
#else #else
EcsDebug.PrintWarning($"Reflection is not available, the {nameof(MetaGenerator)}.{nameof(GetDescription)} method does not work."); EcsDebug.PrintWarning($"Reflection is not available, the {nameof(MetaGenerator)}.{nameof(GetDescription)} method does not work.");
@ -566,10 +619,14 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region GetTags #region GetTags
public static IReadOnlyList<string> GetTags(Type type) public static IReadOnlyList<string> GetTags(TypeMeta meta)
{ {
#if DEBUG || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает #if DEBUG || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает
var atr = type.GetCustomAttribute<MetaTagsAttribute>(); if (meta._proxy.Tags != null)
{
return meta._proxy.Tags.ToArray();
}
var atr = meta.Type.GetCustomAttribute<MetaTagsAttribute>();
return atr != null ? atr.Tags : Array.Empty<string>(); return atr != null ? atr.Tags : Array.Empty<string>();
#else #else
EcsDebug.PrintWarning($"Reflection is not available, the {nameof(MetaGenerator)}.{nameof(GetTags)} method does not work."); EcsDebug.PrintWarning($"Reflection is not available, the {nameof(MetaGenerator)}.{nameof(GetTags)} method does not work.");
@ -624,4 +681,28 @@ namespace DCFApixels.DragonECS
} }
#endregion #endregion
} }
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = true)]
public sealed class MetaProxyAttribute : EcsMetaAttribute
{
public Type Type;
public MetaProxyAttribute(Type type)
{
Type = type;
}
}
public class MetaProxy
{
public static readonly MetaProxy EmptyProxy = new MetaProxy(typeof(void));
public static TypeMeta EmptyMeta => TypeMeta.NullTypeMeta;
public readonly Type Type;
public virtual string Name { get { return null; } }
public virtual MetaColor? Color { get { return null; } }
public virtual MetaDescription Description { get { return null; } }
public virtual MetaGroup Group { get { return null; } }
public virtual IEnumerable<string> Tags { get { return null; } }
public MetaProxy(Type type)
{
Type = type;
}
}
} }

View File

@ -9,6 +9,15 @@ namespace DCFApixels.DragonECS.Core.Internal
{ {
internal static class ReflectionUtility internal static class ReflectionUtility
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Type GetPureType(this Type type)
{
if (type.IsGenericType)
{
return type.GetGenericTypeDefinition();
}
return type;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool TryGetAttribute<T>(this MemberInfo self, out T attribute) where T : Attribute public static bool TryGetAttribute<T>(this MemberInfo self, out T attribute) where T : Attribute
{ {