DragonECS/src/DebugUtils/EcsDebugUtility.cs

319 lines
11 KiB
C#
Raw Normal View History

2024-06-05 14:39:19 +08:00
using System;
2023-06-16 11:53:59 +08:00
using System.Collections.Generic;
2024-08-07 09:45:34 +08:00
#if (DEBUG && !DISABLE_DEBUG) || !REFLECTION_DISABLED
2023-05-23 01:47:28 +08:00
using System.Reflection;
2024-08-07 09:45:34 +08:00
#endif
2023-05-23 01:47:28 +08:00
namespace DCFApixels.DragonECS
{
public static class EcsDebugUtility
{
2024-08-07 09:45:34 +08:00
#if (DEBUG && !DISABLE_DEBUG) || !REFLECTION_DISABLED
private const BindingFlags RFL_FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
2024-08-07 09:45:34 +08:00
#endif
2023-06-16 12:34:54 +08:00
#region GetGenericTypeName
2024-03-06 21:35:34 +08:00
public static string GetGenericTypeFullName<T>(int maxDepth = 2)
{
return GetGenericTypeFullName(typeof(T), maxDepth);
}
public static string GetGenericTypeFullName(Type type, int maxDepth = 2)
{
2024-08-07 09:45:34 +08:00
return GetGenericTypeName_Internal(type, maxDepth, true);
2024-03-06 21:35:34 +08:00
}
public static string GetGenericTypeName<T>(int maxDepth = 2)
{
return GetGenericTypeName(typeof(T), maxDepth);
}
public static string GetGenericTypeName(Type type, int maxDepth = 2)
{
2024-08-07 09:45:34 +08:00
return GetGenericTypeName_Internal(type, maxDepth, false);
2024-03-06 21:35:34 +08:00
}
2024-08-07 09:45:34 +08:00
private static string GetGenericTypeName_Internal(Type type, int maxDepth, bool isFull)
2023-05-23 01:47:28 +08:00
{
2024-08-07 09:45:34 +08:00
#if (DEBUG && !DISABLE_DEBUG) || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает
2024-03-06 21:35:34 +08:00
string typeName = isFull ? type.FullName : type.Name;
2023-05-23 01:47:28 +08:00
if (!type.IsGenericType || maxDepth == 0)
2024-03-06 21:35:34 +08:00
{
return typeName;
}
int genericInfoIndex = typeName.LastIndexOf('`');
if (genericInfoIndex > 0)
{
typeName = typeName.Remove(genericInfoIndex);
}
2023-05-23 01:47:28 +08:00
2024-03-06 21:35:34 +08:00
string genericParams = "";
2023-05-23 01:47:28 +08:00
Type[] typeParameters = type.GetGenericArguments();
for (int i = 0; i < typeParameters.Length; ++i)
{
2024-03-06 21:35:34 +08:00
//чтобы строка не была слишком длинной, используются сокращенные имена для типов аргументов
2024-08-07 09:50:14 +08:00
string paramTypeName = GetGenericTypeName_Internal(typeParameters[i], maxDepth - 1, false);
2024-03-06 21:35:34 +08:00
genericParams += (i == 0 ? paramTypeName : $", {paramTypeName}");
2023-05-23 01:47:28 +08:00
}
2024-03-06 21:35:34 +08:00
return $"{typeName}<{genericParams}>";
2024-08-07 09:45:34 +08:00
#else
EcsDebug.PrintWarning($"Reflection is not available, the {nameof(GetGenericTypeName_Internal)} method does not work.");
return isFull ? type.FullName : type.Name;
#endif
2023-05-23 01:47:28 +08:00
}
2023-06-16 12:34:54 +08:00
#endregion
2023-05-23 01:47:28 +08:00
2023-06-22 10:50:47 +08:00
#region AutoToString
2023-06-22 10:58:57 +08:00
/// <summary> slow but automatic conversion of ValueType to string in the format "name(field1, field2... fieldn)" </summary>
2023-06-22 10:50:47 +08:00
public static string AutoToString<T>(this T self, bool isWriteName = true) where T : struct
{
return AutoToString(self, typeof(T), isWriteName);
}
2024-08-14 21:23:34 +08:00
2024-09-13 11:03:51 +08:00
internal static string AutoToString(object target, Type type, bool isWriteName)
2023-06-22 10:50:47 +08:00
{
2024-08-07 09:45:34 +08:00
#if (DEBUG && !DISABLE_DEBUG) || !REFLECTION_DISABLED //в дебажных утилитах REFLECTION_DISABLED только в релизном билде работает
#pragma warning disable IL2070 // 'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The parameter of method does not have matching annotations.
var fields = type.GetFields(RFL_FLAGS);
#pragma warning restore IL2070
2023-06-22 10:50:47 +08:00
string[] values = new string[fields.Length];
for (int i = 0; i < fields.Length; i++)
{
2023-06-22 11:00:33 +08:00
values[i] = (fields[i].GetValue(target) ?? "NULL").ToString();
}
2023-06-22 10:58:57 +08:00
if (isWriteName)
{
2023-06-22 10:50:47 +08:00
return $"{type.Name}({string.Join(", ", values)})";
}
2023-06-22 10:50:47 +08:00
else
{
2023-06-22 10:50:47 +08:00
return $"({string.Join(", ", values)})";
}
2024-02-26 10:43:37 +08:00
#else
EcsDebug.PrintWarning($"Reflection is not available, the {nameof(AutoToString)} method does not work.");
return string.Empty;
2024-02-26 10:43:37 +08:00
#endif
2023-06-22 10:50:47 +08:00
}
#endregion
2023-06-16 12:34:54 +08:00
#region GetName
2024-03-06 21:35:34 +08:00
public static string GetMetaName(object obj)
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta(obj).Name;
}
2024-03-06 21:35:34 +08:00
public static string GetMetaName<T>()
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta<T>().Name;
}
2024-03-06 21:35:34 +08:00
public static string GetMetaName(Type type)
2023-06-16 11:53:59 +08:00
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta(type).Name;
}
public static bool TryGetMetaName(object obj, out string name)
{
TypeMeta meta = GetTypeMeta(obj);
name = meta.Name;
return meta.IsCustomName;
}
public static bool TryGetMetaName<T>(out string name)
{
TypeMeta meta = GetTypeMeta<T>();
name = meta.Name;
return meta.IsCustomName;
}
public static bool TryGetMetaName(Type type, out string name)
{
TypeMeta meta = GetTypeMeta(type);
name = meta.Name;
return meta.IsCustomName;
2023-06-16 11:53:59 +08:00
}
2023-06-16 12:34:54 +08:00
#endregion
2023-05-23 01:47:28 +08:00
2024-03-06 21:35:34 +08:00
#region GetColor
public static MetaColor GetColor(object obj)
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta(obj).Color;
}
2024-03-06 21:35:34 +08:00
public static MetaColor GetColor<T>()
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta<T>().Color;
}
2024-03-06 21:35:34 +08:00
public static MetaColor GetColor(Type type)
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta(type).Color;
}
public static bool TryGetColor(object obj, out MetaColor color)
{
TypeMeta meta = GetTypeMeta(obj);
color = meta.Color;
return meta.IsCustomColor;
}
public static bool TryGetColor<T>(out MetaColor color)
{
TypeMeta meta = GetTypeMeta<T>();
color = meta.Color;
return meta.IsCustomColor;
}
public static bool TryGetColor(Type type, out MetaColor color)
{
TypeMeta meta = GetTypeMeta(type);
color = meta.Color;
return meta.IsCustomColor;
}
#endregion
2023-06-16 12:34:54 +08:00
#region GetDescription
2024-05-01 13:38:08 +08:00
public static MetaDescription GetDescription(object obj)
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta(obj).Description;
}
2024-05-01 13:38:08 +08:00
public static MetaDescription GetDescription<T>()
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta<T>().Description;
}
2024-05-01 13:38:08 +08:00
public static MetaDescription GetDescription(Type type)
2023-06-16 11:53:59 +08:00
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta(type).Description;
2023-06-16 11:53:59 +08:00
}
2024-05-01 13:38:08 +08:00
public static bool TryGetDescription(object obj, out MetaDescription description)
{
2024-03-06 21:35:34 +08:00
TypeMeta meta = GetTypeMeta(obj);
description = meta.Description;
2024-05-01 13:38:08 +08:00
return description != MetaDescription.Empty;
}
2024-05-01 13:38:08 +08:00
public static bool TryGetDescription<T>(out MetaDescription description)
{
2024-03-06 21:35:34 +08:00
TypeMeta meta = GetTypeMeta<T>();
description = meta.Description;
2024-05-01 13:38:08 +08:00
return description != MetaDescription.Empty;
}
2024-05-01 13:38:08 +08:00
public static bool TryGetDescription(Type type, out MetaDescription description)
2023-05-23 01:47:28 +08:00
{
2024-03-06 21:35:34 +08:00
TypeMeta meta = GetTypeMeta(type);
description = meta.Description;
2024-05-01 13:38:08 +08:00
return description != MetaDescription.Empty;
2024-03-03 00:28:16 +08:00
}
2024-03-06 21:35:34 +08:00
#endregion
#region GetGroup
2024-03-06 23:29:37 +08:00
public static MetaGroup GetGroup(object obj)
2024-03-03 00:28:16 +08:00
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta(obj).Group;
2023-06-16 11:53:59 +08:00
}
2024-03-06 23:29:37 +08:00
public static MetaGroup GetGroup<T>()
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta<T>().Group;
}
2024-03-06 23:29:37 +08:00
public static MetaGroup GetGroup(Type type)
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta(type).Group;
}
2024-03-06 21:35:34 +08:00
2024-03-06 23:29:37 +08:00
public static bool TryGetGroup(object obj, out MetaGroup group)
2023-06-16 11:53:59 +08:00
{
2024-03-06 21:35:34 +08:00
TypeMeta meta = GetTypeMeta(obj);
group = meta.Group;
2024-05-01 13:38:08 +08:00
return group != MetaGroup.Empty;
2024-03-06 21:35:34 +08:00
}
2024-03-06 23:29:37 +08:00
public static bool TryGetGroup<T>(out MetaGroup group)
2024-03-06 21:35:34 +08:00
{
TypeMeta meta = GetTypeMeta<T>();
group = meta.Group;
2024-05-01 13:38:08 +08:00
return group != MetaGroup.Empty;
2024-03-06 21:35:34 +08:00
}
2024-03-06 23:29:37 +08:00
public static bool TryGetGroup(Type type, out MetaGroup group)
2024-03-06 21:35:34 +08:00
{
TypeMeta meta = GetTypeMeta(type);
group = meta.Group;
2024-05-01 13:38:08 +08:00
return group != MetaGroup.Empty;
}
#endregion
#region GetTags
public static IReadOnlyCollection<string> GetTags(object obj)
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta(obj).Tags;
}
public static IReadOnlyCollection<string> GetTags<T>()
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta<T>().Tags;
}
public static IReadOnlyCollection<string> GetTags(Type type)
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta(type).Tags;
}
public static bool TryGetTags(object obj, out IReadOnlyCollection<string> tags)
{
2024-03-06 21:35:34 +08:00
TypeMeta meta = GetTypeMeta(obj);
tags = meta.Tags;
return tags.Count <= 0;
}
public static bool TryGetTags<T>(out IReadOnlyCollection<string> tags)
{
2024-03-06 21:35:34 +08:00
TypeMeta meta = GetTypeMeta<T>();
tags = meta.Tags;
return tags.Count <= 0;
}
public static bool TryGetTags(Type type, out IReadOnlyCollection<string> tags)
{
2024-03-06 21:35:34 +08:00
TypeMeta meta = GetTypeMeta(type);
tags = meta.Tags;
return tags.Count <= 0;
2023-05-23 01:47:28 +08:00
}
2023-06-16 11:53:59 +08:00
#endregion
2023-05-31 04:09:55 +08:00
2023-06-16 12:34:54 +08:00
#region IsHidden
public static bool IsHidden(object obj)
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta(obj).IsHidden;
}
public static bool IsHidden<T>()
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta<T>().IsHidden;
}
public static bool IsHidden(Type type)
{
2024-03-06 21:35:34 +08:00
return GetTypeMeta(type).IsHidden;
}
2023-06-16 12:34:54 +08:00
#endregion
2024-03-06 21:35:34 +08:00
#region GetTypeMeta
public static TypeMeta GetTypeMeta(object obj)
{
2024-09-27 21:46:16 +08:00
if (obj == null) { return TypeMeta.NullTypeMeta; }
2024-06-05 14:39:19 +08:00
return TypeMeta.Get(GetTypeMetaSource(obj).GetType());
}
2024-03-06 21:35:34 +08:00
public static TypeMeta GetTypeMeta<T>()
{
2024-06-05 14:39:19 +08:00
return TypeMeta.Get(typeof(T));
}
2024-03-06 21:35:34 +08:00
public static TypeMeta GetTypeMeta(Type type)
{
2024-06-05 14:39:19 +08:00
return TypeMeta.Get(type);
}
#endregion
2024-08-07 09:45:34 +08:00
#region TypeMetaProvider
2024-03-06 21:35:34 +08:00
public static bool IsTypeMetaProvided(object obj)
2023-05-31 04:09:55 +08:00
{
2024-03-06 21:35:34 +08:00
return obj is IEcsTypeMetaProvider;
2023-05-31 04:09:55 +08:00
}
2024-03-06 21:35:34 +08:00
public static object GetTypeMetaSource(object obj)
2023-06-16 12:34:54 +08:00
{
2024-03-06 21:35:34 +08:00
return obj is IEcsTypeMetaProvider intr ? intr.MetaSource : obj;
2023-06-16 12:34:54 +08:00
}
#endregion
}
2024-03-10 01:25:08 +08:00
public static class TypeMetaDataCachedExtensions
{
public static TypeMeta GetMeta(this object self)
2024-03-06 21:35:34 +08:00
{
2024-03-10 01:25:08 +08:00
return EcsDebugUtility.GetTypeMeta(self);
2024-03-06 21:35:34 +08:00
}
2024-03-10 01:25:08 +08:00
public static TypeMeta ToMeta(this Type self)
2024-03-06 21:35:34 +08:00
{
2024-03-10 01:25:08 +08:00
return EcsDebugUtility.GetTypeMeta(self);
2024-03-06 21:35:34 +08:00
}
}
}